Java学习之三个修饰符(abstract、static、final),干货满满!
大家好今天Java学习的内容是三个修饰符abstract、static、final。这三个修饰符非常重要面试经常考开发也天天用。今天的内容比较多但整理完之后感觉思路清晰了很多。下面是我的学习总结。一、abstract抽象的1. abstract修饰类 → 抽象类语法abstract class 类名 { }特点抽象类会生成独立的.class文件不能单独创建对象不能new但可以声明引用抽象类中可以有成员变量和成员方法抽象类中有构造方法供子类创建对象时调用2. abstract修饰方法 → 抽象方法语法访问修饰符 abstract 返回值类型 方法名(形参列表); // 注意没有方法体连{}都没有直接分号结尾特点抽象方法只有声明没有实现抽象方法只能定义在抽象类中抽象类中既可以有抽象方法也可以有非抽象方法3. 子类继承抽象类的要求abstract class Animal { public abstract void sound(); // 抽象方法 public void eat() { // 非抽象方法 System.out.println(吃东西); } } // 方式1子类覆盖所有抽象方法 → 普通类 class Dog extends Animal { Override public void sound() { System.out.println(汪汪汪); } } // 方式2子类不覆盖所有抽象方法 → 也必须是抽象类 abstract class Cat extends Animal { // 没有覆盖sound()Cat也必须是抽象类 }4. 抽象类的作用强制使用多态抽象类不能创建对象只能通过子类实例化天然就是父类引用指向子类对象。Animal a new Dog(); // 多态 a.sound(); // 汪汪汪二、static静态的1. static修饰属性 → 静态属性/类变量语法访问修饰符 static 数据类型 属性名;特点静态属性是全类共有的与创建多少对象无关所有对象共享同一个静态属性使用方式class MyClass { int value 10; // 实例变量 static int b 30; // 静态变量 } public class TestStatic { public static void main(String[] args) { MyClass mc1 new MyClass(); MyClass mc2 new MyClass(); mc1.value 50; // 只改了mc1的 mc1.b 48; // 改了共享的静态变量 System.out.println(mc1.value); // 50 System.out.println(mc2.value); // 10没变 System.out.println(mc1.b); // 48 System.out.println(mc2.b); // 48共享的 // 推荐使用类名访问 MyClass.b 100; } }2. static修饰方法 → 静态方法语法访问修饰符 static 返回值类型 方法名(形参列表) { // 方法体 }使用类名.静态方法名(实参); // 推荐 对象名.静态方法名(实参); // 不推荐重要规则面试常考class Demo { static int staticVar 10; int instanceVar 20; // 静态方法 public static void staticMethod() { // ✅ 可以访问静态成员 System.out.println(staticVar); // ❌ 不能直接访问非静态成员 // System.out.println(instanceVar); // 编译报错 // ❌ 不能使用this和super // this.instanceVar 30; // 编译报错 // ✅ 可以通过创建对象访问非静态成员 Demo d new Demo(); System.out.println(d.instanceVar); } // 非静态方法 public void instanceMethod() { // ✅ 可以访问静态成员 System.out.println(staticVar); // ✅ 可以访问非静态成员 System.out.println(instanceVar); } }3. static修饰代码块 → 静态代码块动态代码块了解class Demo { int value; { // 动态代码块创建对象时执行用于初始化实例变量 value 10; System.out.println(动态代码块); } }静态代码块重点class Demo { static int num; static { // 静态代码块类加载时执行用于初始化静态变量 num 100; System.out.println(静态代码块); } }4. 类加载重要什么是类加载JVM第一次使用一个类时读取.class文件信息并存储在内存中一个类只加载一次。类加载的时机第一次创建该类的对象第一次使用该类的静态成员子类加载会导致父类先加载完整执行顺序面试常考class Parent { static int a 10; int b 20; static { System.out.println(父类静态代码块); } { System.out.println(父类动态代码块); } public Parent() { System.out.println(父类构造方法); } } class Child extends Parent { static int c 30; int d 40; static { System.out.println(子类静态代码块); } { System.out.println(子类动态代码块); } public Child() { System.out.println(子类构造方法); } } // 执行 new Child() 的输出顺序 // 父类静态代码块 // 子类静态代码块 // 父类动态代码块 // 父类构造方法 // 子类动态代码块 // 子类构造方法注意只声明引用不会导致类加载Child c; // 不会加载类 c new Child(); // 这时才加载三、final最终的1. final修饰变量 → 常量特点只能赋值一次不能再改。// 局部常量 final int MAX 100; MAX 200; // ❌ 编译报错 // 实例常量必须初始化 class Demo { final int a; // 必须在构造方法或动态代码块中初始化 final int b 10; // 声明时初始化 { a 20; // 动态代码块初始化 } } // 静态常量必须初始化 class Demo2 { static final int C; // 必须在静态代码块中初始化 static { C 30; } }final修饰引用final Dog d new Dog(); d.name 旺财; // ✅ 对象的内容可以改 d new Dog(); // ❌ 不能指向新对象地址不能变2. final修饰方法 → 不能被子类重写class Parent { public final void method() { System.out.println(父类方法); } } class Child extends Parent { // public void method() { } // ❌ 编译报错不能重写 }3. final修饰类 → 不能被继承final class String { // ... } // class MyString extends String { } // ❌ 报错String是final类常见的final类String、System、Math等。四、三个修饰符总结修饰符修饰类修饰方法修饰变量abstract抽象类不能实例化抽象方法无实现❌ 不能static❌ 不能内部类可以静态方法类名调用静态变量全类共享final不能被继承不能被重写常量只能赋值一次五、我踩过的坑坑1静态方法中访问非静态成员class Demo { int value 10; public static void main(String[] args) { System.out.println(value); // ❌ 编译报错 } }解决创建对象再访问或者把value也改成静态的。坑2抽象类忘记写子类覆盖所有抽象方法abstract class Animal { public abstract void sound(); } class Dog extends Animal { // 忘记重写sound()编译报错 }解决要么重写所有抽象方法要么把子类也定义为抽象类。坑3final变量未初始化class Demo { final int a; // ❌ 编译报错没有初始化 }解决在声明时、构造方法中或动态代码块中初始化。坑4静态代码块和动态代码块搞混static { // 这是静态代码块类加载时执行一次 } { // 这是动态代码块每次创建对象都执行 }解决记住static关键字有static是静态代码块没有是动态代码块。六、面试高频题抽象类和接口的区别后面会学接口静态方法为什么不能直接访问非静态成员答静态方法在类加载时就存在此时非静态成员还没有创建静态代码块和动态代码块的区别静态代码块类加载时执行一次用于初始化静态变量动态代码块每次创建对象都执行用于初始化实例变量final、finally、finalize的区别经典面试题final修饰符表示常量、不可重写、不可继承finally异常处理中的finally块finalizeObject类的方法垃圾回收时调用七、小思考System.out.println()的原理System.out.println(hello);System是java.lang包下的一个类out是System类中的静态属性类型是PrintStreamprintln()是PrintStream类中的方法相当于class System { static PrintStream out new PrintStream(); } class PrintStream { public void println(String s) { // 打印输出 } }我接下来的任务把课堂上的案例都敲一遍比如用抽象类实现图形面积计算、用静态属性统计创建了多少个对象等加上注释再做一些练习题巩固。如果你也在学Java欢迎一起交流我们明天继续