食用前说明:10.1 类变量和类方法本文章内容来自B站韩顺平老师的课堂笔记,本人只是将其进行自我整理,内容有所删减,韩顺平老师的B站课程AV号:BV1fh411y7R8
本文章内容来自韩顺平老师的课堂笔记的 第10章 面向对象编程 (高级部分),本章内容重点掌握:类变量和类方法、接口、内部类。
附上本章开始链接:
类变量与类方法
- 类变量和类方法
-
访问修饰符 static 数据类型 变量名: [推荐] public static int count = 0; static 访问修饰符 数据类型 变量名;
案例演示
-
public static String name = "伍六七";
10.1.3 类变量使用注意事项和细节
什么时候需要用类变量
当我们需要让某个类的所有对象都共享一个变量时,就可以考虑使用类变量(静态变量)
类变量可以通过 类名.类变量名 或者对象名.类变量名 来访问
推荐使用:类名.类变量名 方式访问。
//假设我们要访问C类的address变量 System.out.println(C.address);//输出address变量条件:满足访问修饰符的访问
实例变量不能通过 类名.类变量名 方式访问。
类变量是在类加载时就初始化了,也就是说,即使你没有创建对象,只要类加载了,就可以使用类变量了。
类变量的生命周期:随类的加载开始,随着类消亡而销毁。
名称 普通属性区别 如何区分 类变量 所有对象共享 有 static 实例变量 每个对象独享 无 static
10.1.4 类方法基本介绍
-
语法
-
//静态方法 访问修饰符 static 数据类型 方法名: [推荐] static 访问修饰符 数据类型 方法名;
- 案例演示
-
public static void showFee() {...}
10.1.5 类方法使用注意事项和细节
类方法和普通方法都是随着类的加载而加载,将结构信息储存在方法区:
类方法中无 this 的参数
普通方法中隐含着 this 的参数
类方法可以通过类名调用,也可以通过对象名调用。
普通方法和对象有关,需要通过对象名调用,比如 对象名.方法名(参数) ,不能通过类名调用
案例演示
public static void main(String[] args) { D.hi();//可以调用 D.say();// 报错,非静态方法,不能通过类名调用 } class D { public void say() {//非静态方法,普通方法 } public static void hi() {//静态方法 } }类方法中不允许使用和对象有关的关键字,比如 this 和 super 。普通方法(成员方法)可以。
类方法(静态方法)中 只能访问 静态变量 或静态方法 口诀:静态方法只能访问静态成员
普通成员方法,既可以访问 非静态成员,也可以访问静态成员。
-
小结: 静态方法,只能访问静态的成员,非静态的方法,可以访问静态成员和非静态成员(必须遵守访问权限)
-
什么时候需要用类方法
-
当方法中不涉及到任何和对象相关的成员,可以将方法设计成静态方法,提高开发效率
-
-
小结 在程序员实际开发,往往会将一些通用的方法,设计成静态方法,这样我们不需要创建对象就可以使用, 比如打印一维数组,冒泡排序,完成某个计算任务 等.
深入理解 main 方法
main 方法的形式:
public static void main(String[] args){...}
main 方法是虚拟机调用
Java虚拟机需要调用类的 main() 方法,所以该方法的访问权限必须是 public
Java虚拟机在执行main()方法时不必创建对象,所以该方法必须是 static
该方法接收 String 类型的数组参数,该数组中保存执行 java 命令时传递给所运行的类的参数。
Java 执行的程序 参数1 参数2 参数3
10.2.1 特别提示:
-
在 main() 方法中,我们可以直接调用 main 方法所在类的静态方法或静态属性。
-
但是,不能直接访问该类中的非静态成员,必须创建该类的一个实例对象后,才能通过这个对象去访问类中的非静态成员。
可以简单的认为:用 { } 包围起来的代码
代码块和方法不同:没有方法名,返回参数,只有方法体。
访问访问形式不同:不通过对象或类显式调用,而是加载类时或创建对象式 隐式调用。
-
说明注意:
-
修饰符 可选,要写的话,也只能写 static
-
代码块分为两类,使用 static 修饰的叫静态代码块,没有 static 修饰的,叫普通代码块/非静态代码块。
-
逻辑语句可以为任何逻辑语句(输入、输出、方法调用、循环、判断等)
-
; 号可以写上,也可以省略。
-
-
{ System.out.println("静态..."); System.out.println("代码块..."); System.out.println("加载..."); };
10.3.1 代码块使用注意事项和细节
静态代码块只能直接调用静态成员 (静态属性 和 静态方法)
静态代码块作用:对类进行初始化,随着类的加载而执行,并且只执行一次。如果是普通代码块,每创建一个对象,就执行。
案例演示:A类 extends B类 的静态块
案例演示
//类被加载的情况举例 //1. 创建对象实例时(new) // AA aa = new AA(); //2. 创建子类对象实例,父类也会被加载, 而且,父类先被加载,子类后被加载 // AA aa2 = new AA(); //3. 使用类的静态成员时(静态属性,静态方法) // System.out.println(Cat.n1); //static 代码块,是在类加载时,执行的,而且只会执行一次. class Animal { //静态代码块 static { System.out.println("Animal 的静态代码 1 被执行...");// } } class Cat extends Animal { public static int n1 = 999;//静态属性 //静态代码块 static { System.out.println("Cat 的静态代码 1 被执行...");// } } class BB { //静态代码块 static { System.out.println("BB 的静态代码 1 被执行...");//1 } } class AA extends BB { //静态代码块 static { System.out.println("AA 的静态代码 1 被执行...");//2 } }普通代码块,在创建对象实例时,会被隐式调用。被创建一次就调用一次。若只使用类的静态成员时,普通代码块不会执行。
构造器 隐含了 super() 和 调用普通代码块
-
小结:
-
static代码块是类加载是,执行,只会执行一次
-
普通代码块是在创建对象时调用,创建一次,调用一次。
-
类加载的3种情况,需记住❗
-
❗:类什么时候被加载 [ 重要背! ]
-
① 创建对象实例时(new)
AA aa = new AA();
-
② 创建子类对象实例,父类也会被加载 (父类先被加载)
-
③ 使用类的静态成员时(静态属性,静态方法)
10.3.2 创建对象时类的调用顺序(重点、难点)
-
调用静态代码块和讲静态属性的初始化 ( ❗:静态代码块和静态属性调用优先级一样,按照它们定义的顺序调用。)
-
调用普通代码块和普通属性的初始化 ( ❗:普通代码块和普通属性调用优先级一样,按照它们定义的顺序调用。)
-
调用构造方法。
10.3.3 构造方法的调用顺序:
10.4 单例设计模式
父类的静态代码块和静态属性 (它俩优先级一样,按定义顺序执行)
子类的静态代码块和静态属性 (它俩优先级一样,按定义顺序执行)
父类的普通代码块和属性初始化 (它俩优先级一样,按定义顺序执行)
父类的构造方法
子类的普通代码块和属性初始化 (它俩优先级一样,按定义顺序执行)
子类的构造方法
10.5 final 关键字待补齐
10.4.1 什么是单例模式
10.5.1 基本介绍
在以下情况,程序员可能有以下需求,就会使用到final:
当不希望类被继承时,可以用final修饰。
当不希望父类的某个方法被子类覆盖/重写(override)时,可以用final关键字修饰。 【案例演示: 访问修饰符 final 返回类型 方法名 】
当不希望类的的某个属性的值被修改,可以用final修饰。【演示: public final double TAX_RATE=0.08】
当不希望某个局部变量被修改,可以使用final修饰 【案例演示:final double TAX RATE=0.08】
-
final 修饰符一边应用基本 (primitive) 类型域,或不可变 (immutable) 类的域(也可修饰:类里面都为不会改变的对象的方法)
10.5.2 final 使用注意事项 和 细节讨论
-
final 修饰的属性在定义时, 必须赋初值, 并且不能修改,赋值可在如下位置: ①定义时; ②在构造器中; ③在代码块中。
-
class AA { public final double TAX_RATE = 0.08;//1.定义时赋值 public final double TAX_RATE2 ; public final double TAX_RATE3 ; public AA() {//构造器中赋值 TAX_RATE2 = 1.1; } {//在代码块赋值 TAX_RATE3 = 8.8; } }
-
-
若 final 修饰的属性是静态的,则初始化的位置只能是:
-
①定义时; ②在静态代码块 不能在构造器中赋值。
-
-
关于 final 修饰的类能不能被继承:
-
fina 修饰的类不能被继承, 但可以实例化对象。
-
类不是被 final 修饰, 但是含有 final 修饰的方法, 则该方法虽然不能重写, 但可以被继承。
-
-
类被 final 修饰了, 该类的方法就没必要再用 final 修饰。
-
final 不能修饰构造器。
-
final 和 static 往往搭配使用, 效率更高, 不会导致类加载。底层编译器做了优化处理
public static final int i = 16;
-
-
包装类 (Integer, Double, Float, Boolean 等都是 final ), String 也是 final 类。
10.6.1 抽象类基本介绍
10.7 抽象类最佳实践-模板设计模式
abstract 修饰方法时格式
访问修饰符 abstract 类名{...} //抽象类不一定要包含 abstract 方法。也就是说,抽象类可以没有 abstract 方法 //,还可以有实现的方法。 abstract class A { public void hi() { System.out.println("hi"); } } //一旦类包含了 abstract 方法,则这个类必须声明为 abstract abstract class B { public abstract void hi(); }abstract 修饰方法时格式:
访问修饰符 abstract 返回类型 方法名();//没有方法体 public abstract void hi();
抽象类的价值更多作用于设计, 是设计者设计好后,让子类继承并实现抽象类方法。
类继承抽象类后, 必须实现抽象类的所有抽象方法, 除非它自己也声明为 abstract 类。
抽象方法不能使用 private、final 和 static 来修饰, 因为这些关键字都是和重写相违背。
10.7.1 模板设计模式能解决的问题
当功能内部一部分实现是确定, 一部分实现是不确定的。这时可以把不确定的部分暴露出去, 让给子类实现。
编写一个抽象父类, 父类提供了多个子类的通用方法, 并把一个或多个方法留给其子类实现, 就是一种模板模式。



