第七章:(面向对象-高级)
1、类变量(静态变量)
- static变量是同一个类所有对象共享的
- static在类加载的时候就生成了
什么是类变量?
类变量也叫静态变量/静态属性,是该类所有对象共享的变量,该类的任何一个对象访问它时,取到的都是相同的值,同样任何一个该类的对象去修改它时,修改的也是同一个变量
定义语法:
访问修饰符 static 数据类型 变量名;【推荐】
static 访问修饰符 数据类型 变量名;
如何访问类变量:
类名 . 变量名;【推荐】 或者 对象名 . 变量名 ;
静态变量的访问修饰符的访问权限 和 普通属性是一样的
1.1 使用细节
-
什么时候需要用类变量
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量
-
类变量与实例变量(非静态变量)的区别
类变量是该类所有对象共享的,而实例变量是每个对象独享的
-
类变量可以通过类名.变量名访问 或者对象名.变量名;前提是满足访问修饰符的权限;
-
实例变量不能通过 类名.变量名方式访问
-
类变量是在类加载时就就初始化了,也就是说,即使你没有创建对象,只要类加载了,就可以使用类变量了
-
类变量的生命周期是随着类的加载开始,随着类的消亡而销毁
2、类方法(静态方法)
基本介绍:
类方法也叫静态方法。
语法:
访问修饰符 static 数据返回类型 方法名(){}【推荐】;
static 访问修饰符 数据返回类型 方法名(){};
调用:
类名.方法名 或者 对象名.方法名
类方法的使用场景:
比如:工具类中的方法 Utils
Math类、Arrays类、Collection集合类
在程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用了,比如打印一维数组,冒泡排序,完成某个计算任务等…
2.1 使用细节
- 类方法和普通方法都是随着类的加载而加载,将结构信息存储在方法区
- 类方法中不能使用this,即不能使用与对象有关的关键字
- 类方法可以通过类名调用,也可以通过对象名调用
- 静态方法(类方法)只能访问静态成员(类)
- 普通成员方法,既可以访问非静态成员,也可以访问静态成员
4、main方法
深入理解main方法
解释main方法的形式:public static void main(Stringll args)
-
main方法是由虚拟机调用
-
java虚拟机需要调用类的main()方法,所以该方法的访问权限必须是public
-
java虚拟机在执行main()方法时不必创建对象,所以该方法必须是static
-
该方法接收String类型的数组参数,该数组中保存执行java命令时传递给所运行的类的参数案例演示,接收参数.
D:\SublimeText> java hello 参数1 参数2 参数3
5、代码块
基本介绍:
代码块又称为初始化块,属于类中的成员【即是类中的一部分】
基本语法:
[修饰符]{
代码
};
注意:
- 修饰符可不写,要写的话,也只能写static
- 代码块分为两种,使用static修饰的叫静态代码块,没有static修饰的,叫普通代码块
- 分号可写可不写
- 代码块的调用优先于构造器
代码块的好处:
- 相当于另外一种形式的构造器(对构造器的补充机制),可以做初始化的操作
- 如果多个构造器中都有重复的语句,可以抽取到初始化块中
5.1 使用细节
- static代码块也叫静态代码块,作用就是对类进行初始化,而且随着类的加载而执行。
- 静态代码块只能调用静态成员
- 如果是普通代码块,每创建一个对象,就执行一次。
5.2 类什么时候被加载?
- 创建对象实例时(new)
- 创建子类对象实例时,父类也会被加载,而且父类先被加载,子类后被加载
- 使用类的静态成员时(静态属性,静态方法)
- 普通的代码块,在创建对象实例时,会被隐式的调用。被创建一次,就会调用一次。
6、类的调用顺序
创建一个对象时,在一个类中的调用顺序:1、2、3
- 静态属性和静态代码块的优先级相同,如果有多个静态代码块和多个静态变量初始化,则按他们定义的顺序调用
- 普通代码块和普通属性的初始化的优先级相同,如果有多个普通代码块和多个普通属性初始化,则按定义的顺序调用
- 构造器
细节:
-
构造器的最前面其实隐含了super()和 调用普通代码块和普通属性初始化
public Person(){//构造器 //隐含了super() //初始化普通属性或代码块 }
继承关系中,类中的调用顺序:
- 父类的静态属性初始化和静态代码块(两者优先级相同,按定义顺序)
- 子类的静态属性初始化和静态代码块(两者优先级相同,按定义顺序)
- 父类的普通属性初始化和普通代码块(两者优先级相同,按定义顺序)
- 执行父类的构造方法内容
- 子类的普通属性初始化和普通代码块(两者优先级相同,按定义顺序)
- 子类的构造方法
举例:
public class Test {
public static void main(String[] args) {
new B();
}
}
class A {//父类
public static int num = getNum();
int numA = getNumA();
private int getNumA() {
System.out.println("普通变量调用-->A类的普通变量初始化");//(3)
return 1;
}
public A() {
//隐含了 super();和普通变量或普通代码块的初始化
System.out.println("A类的构造器被调用");//(4)
}
public static int getNum() {
System.out.println("静态变量调用-->A类的getNum被调用");//(1)
return 1;
}
}
class B extends A {//子类
public static int num = getNum();
int numB = getNumB();
private int getNumB() {
System.out.println("普通变量调用-->B类的普通变量初始化");//(5)
return 1;
}
public B() {
//隐含了 super();
//和普通变量或普通代码块的初始化
System.out.println("B类的构造器被调用");//(6)
}
public static int getNum() {
System.out.println("静态变量调用-->B类的getNum被调用");//(2)
return 1;
}
}
输出:
静态变量调用-->A类的getNum被调用
静态变量调用-->B类的getNum被调用
普通变量调用-->A类的普通变量初始化
A类的构造器被调用
普通变量调用-->B类的普通变量初始化
B类的构造器被调用