面向对象(高级)(一)

简介: 面向对象(高级)

每个人都可以活得更精彩,不要让惰性毁了你,坚持学习。


随着我们对面向对象的不断了解,我们已经学过很多语法和思想了,虽然不是很好理解,但是也没有难到令人放弃,随着不断地练习,总有一天自己会瞬间通透的;更难学的还在后面。不要觉得Java很难,多给自己点信心,加油。


那好,聊到这里我们继续学习更难的知识点。


1. 类变量和类方法(静态变量)


类变量(静态变量)


引出: 假设有一群小孩在堆雪人,不断地有小孩要加入;问;某个时刻共有多少个小孩?

思路: main中定义count,每个小孩加入后count++。


问题分析: count是个独立对象,访问起来很麻烦,并且没有用到面向对象(OOP)

问题解决: 在类中引入一个类变量(静态变量)static修饰 ,该变量最大的特点就是被该程序中的所有对象共有。

例如:

public class demo {
    public static void main(String[] args) {
        new Child("小明");
         new Child("小红");
        System.out.println(Child.count);
    }
}
class Child {
    private String name;
    public static int count = 0;
    public Child(String name) {
        this.name = name;
        count++;
    }
}


1375cfd0a43048f9813d9757852774d5.png


图示:


aae5c43b9a044507bc271cbb36e3a233.png


内存刨析:

随着版本的不同,静态变量存放的位置不同。

有的书是这样得:


e4f81a2f15814537bb5fb893c9963b75.png

而有的书是说,static得信息存在静态域中:


ff8fd6ee661749cdb82da8ecfe3ea862.png


无论放在哪里,对我们的使用并不影响。

注意事项和使用细节:

🐤  何时使用:需要所有对象共享一个变量

🐤  类变量和实例变量(普通变量)的区别:


类变量是该类所有对象所共享对的,而实例变量是个类对象独有的。


🐤  加上static成为类变量或静态变量,否则称之为实例对象、非静态变量或普通变量。


🐤  类变量的访问方式:


1. 在同一个类中访问:直接引用变量名即可


2. 在不同类中访问:必须通过类名.类变量名字;如:Child.count


原因:类变量是随着类的加载而加载的,所以在类的加载时就可以访问到类变量信息。


🐤  类变量的周期从类的开始到类的结束。



类方法(静态方法):

语法形式:

访问修饰符        static     返回类型        方法名() {     }   (推荐)      或者

static        访问修饰符        返回类型        方法名() {     }   (不推荐)


调用:  


语法:类名.方法名 或者 对象名.方法名 (前提是满足访问修饰符的访问权限和范围)

注意:

非静态的可以调用静态的,但静态的只能调用静态的不可以调用非静态的。

在程序运行时,类先加载,静态此时也就加载,在对象创建后才有了非静态;所以时先有静态后有非静态。


使用场景:

当方法不涉及到任何和对象相关的成员时,则可以将其设为静态方法,以便提升效率。

比如:工具类中的Utils、Math工具、Array类。


注意事项和细节讨论:


🐤 类方法和普通方法都是随着类的加载而加载的,将结构信息储存在方法区:


类方法中无this的参数


而普通方法隐藏着this的参数


🐤类方法可以通过类名调用,也可以通过方法名调用


🐤普通方法和对象有关,需要通过对象名调用,比如:对象名.方法名(参数)【dog.eat()】 不能通过类名调用


例如:

class Dog {
    public void say()  {
        //非静态
    }
    public static void hi(){
        //静态
    }
}
public class demo {
    public static void main(String[] args) {
        Dog.hi();
        Dog.say();//报错
    }
}


7bab84fa36664abc92a416dce951b158.png


🐤 类方法中不允许使用与对象有关的关键字,例如:this和super

🐤 类方法只能访问静态变量或静态方法,而普通成员中既可以访问静态也可以访问非静态

总结:静态可以访问静态的,非静态可以访问静态和非静态的。


2. main方法中的语法

深入理解main方法

1. mian方法被Java虚拟机调用

2. Java虚拟机调用main方法访问权限必须是public


3. Java虚拟机在执行main方法时不需要创建对象,所以i方法必须是static的


4.该方法接受String类型的数组传参,该数组中保存执行Java命令时传递所给类的参数:


也就是我们main方法中的这个:


bdf926e1e0f247f496668bbba4e6c96d.png

String[] args  值是由执行程序时传进去的参数形成的一个数组。


例如:

public class Main {
    private static String name = "小明";
    private int age = 10;
    public static void main(String[] args) {
        System.out.println(name);
        hi();
        System.out.println(age);//错位,main中可以访问静态的,但是不可以访问非静态的
    }
    public static void hi() {
        System.out.println("hello");
    }
}


5b6c65215ffe466d98956a8fb3947a7f.png

6111c81265dd408ab41ba7778acd32c0.png


提示:

🐔: 在main方法中,我们可以直接调用main方法所在类的静态方法或静态属性

🐔: 但是,不能直接调用非静态的成员变量;想要调用,只能通过关键字 new 出实例对象,通过对象去访问。

如何在idea上实现main的动态传值:


由于我的是社区版的我就把b站老韩的视频链接放下来:


0384_韩顺平Java_main动态传值_哔哩哔哩_bilibili

https://www.bilibili.com/video/BV1fh411y7R8?p=385&vd_source=93857e709631270a9e771d5aaee79ecb

3. 代码块

基本介绍:代码块又称初始化块,属于类中的成员【即类的一部分】,类似于方法,讲语法封装在方法体中,用 { } 包围起来。


但和方法不同,无名,无参,无返回值,只是在类加载时,或创建对象时隐式调用。

语法:

修饰符{

       代码

};//“ ;”可写可不写


根据代码块定义的位置以及关键字,又可分为以下四种:

普通代码块

构造块

静态块

同步代码块(后续讲解多线程部分再谈)

🐔 普通代码块


此时的修饰符就是default默认不写;

{

       代码

}

🐔 静态代码块

此时的修饰符就是static

static{

       代码

}

🐔 构造块


定义在类中的代码块(不加修饰符)。也叫:实例代码块。构造代码块一般用于初始化实例成员变量

使用场景:

如果多个构造器中都有重复的语句,可以抽取到初始化块中,提高代码的复用性。

举例:🌰

public class Student{
    private String name;
    private String gender;
    private int age;
    private double score;
    private static String classRoom;
    //实例代码块
    {
        this.name = "marry";
        this.age = 12;
        this.gender = "man";
        System.out.println(name+" is instance init()!");
    } 
    // 静态代码块
    static {
        classRoom = "303";
        System.out.println("I am static init()!");
    }
    // 构造代码块
    public Student(){
        System.out.println("I am Student init()!");
    }
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();
    }
}


b5546d256d624c1aa64108714dfcc13f.png


从这个例子我们可以看出如下总结:


🐔创建对象时,会有如下顺序:

执行静态代码块 ——> 执行普通代码块 ——> 执行构造代码块


🐔 静态代码块仅执行一次,静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的


🐔如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)


🐔实例代码块只有在创建对象时才会执行

如果我们在此基础上加上继承,结构又会如何,执行顺序又会如何?

public class demo {
    public static void main(String[] args) {
         new Son();
    }
}
class Father {
    public Father() {
        System.out.println("我是父类的构造代码块");
    }
    {
        System.out.println("我是父类的代码块");
    }
    static{
        System.out.println("我是父类静态代码块");
    }
}
class Son extends Father{
    public Son() {
        System.out.println("我是子类的构造代码块");
    }
    {
        System.out.println("我是子类的代码块");
    }
    static{
        System.out.println("我是子类静态代码块");
    }
}


3bfd1e8be0f04b74b5ee52c0ea52112a.png


可以发现如下顺序:


执行父类静态代码块 ——> 执行子类静态代码块 ——> 执行父类普通代码块 ——> 执行父类构造代码块——> 执行普通代码块 ——> 执行构造代码块


相关文章
|
3月前
|
C++
C++从入门到精通:2.1.2函数和类——深入学习面向对象的编程基础
C++从入门到精通:2.1.2函数和类——深入学习面向对象的编程基础
|
10月前
|
自然语言处理 JavaScript 前端开发
程序设计语言概述
程序设计语言是用于编写计算机程序的一种形式化语言。它提供了一套语法和语义规则,用于描述计算机程序的结构和行为。
240 0
|
设计模式 存储 安全
Java面向对象编程高级
Java面向对象编程高级
10075 0
Java面向对象编程高级
|
前端开发 JavaScript
来认识一下 styleSheets,好像有点高级的样子
使用 js 操作样式我们通常操作的是 dom 的 style 属性,也就是我们所说的行内样式,那么有没有一种方法可以操作 css 文件中的样式呢?答案是肯定的,我们可以使用 cssom 来操作 css
131 0
|
编译器 C++
C++之面向对象(下)(一)
C++之面向对象(下)(一)
33 0
|
编译器 C++
C++之面向对象(下)(二)
C++之面向对象(下)(二)
64 0
|
编译器 C语言 C++
C++之面向对象(上)(一)
C++之面向对象(上)(一)
65 0
|
存储 编译器 C++
C++之面向对象(中)(二)
C++之面向对象(中)(二)
46 0
|
存储 编译器 C语言
C++之面向对象(上)(三)
C++之面向对象(上)(三)
41 0
|
存储 编译器 C语言
C++之面向对象(上)(二)
C++之面向对象(上)(二)
75 0