Java 三个修饰符

162 阅读5分钟

修饰符

abstract、static、final

abstract

在程序中,定义了多个类,如果这些类中有共同属性、共同方法,通常会将这些共性抽取出来,放在其父类中;如果这个父类只具备某种对象的特征,并不完整,那就将其定义为抽象类。

  1. abstract 修饰类被称为抽象类,不能「new」对象;
  2. 可以被子类继承,为子类提供共性的属性和方法;
  3. 可以声明引用,实现多态;
  4. 抽象类构造方法的作用:构建子类对象时,先构建父类对象。

abstract修饰类:不能 new 对象,但可以声明引用;abstract 修饰方法:只能声明方法,没有方法实现;抽象类中不一定有抽象方法,但有抽象方法的类一定是抽象类;子类继承抽象类后,必须重写抽象类中所有的抽象方法,否则子类仍要定义为抽象类。

public abstract class 类名 {
    public abstract void 方法名(); // 抽象方法
    
    public void 方法名() {
    
    }
}

static

译为静态,static关键字可以修饰属性、方法和代码块。被static修饰的属性为「静态属性」(类属性),被static修饰的方法为「静态方法」(类方法);静态成员是全类所有对象共享的成员,只有一份;访问静态成员时,不必创建对象,如果在本类中,直接通过方法名进行调用,而在其他类中需要类名.属性名类名.方法名进行调用。

实例属性:实例属性是每个对象各自的属性,每个对象都有自己独立的空间,对某一个对象属性的修改,不会影响其他对象的属性。

静态属性:静态属性是整个类共同持有的属性,在方法区中创建,只有一份,任何对象对其修改,都会造成影响。

静态方法特点

  • 静态方法允许直接访问静态成员
  • 静态方法不能直接访问非静态成员
  • 静态方法中不允许使用thissuper关键字
  • 静态方法可以继承,不能重写、没有多态

类加载

JVM」首次使用某个类时,需通过「CLASSPATH」查找该类的「.class」文件。将「.class」文件中对类的描述信息加载到内存中,进行保存。如:包名、类名、父类、属性、方法、构造方法...。什么时候进行类加载呢?

  • 创建对象
  • 创建子类对象
  • 访问静态属性
  • 访问静态方法
  • 主动加载:Class.forName("全限定名")

代码块

  1. 局部代码块

主要是限定变量的使用范围(基本不用)

public class CodeBlock {
    public static void main(String[] args) {
        // 局部代码块
        {
            int age = 10;
            System.out.println(age);
        }
        int num = 20;
        System.out.println(num);
    }
}
  1. 动态代码块

动态代码块在创建对象时会执行,而且每创建一个对象就会执行一次。执行顺序为:字段初始化 -> 动态代码块 -> 构造器。下面的例子在编译时会报错Cannot read value of field 'name' before the field's definition正确的应该经报错位置改为System.out.println(this.name + this.age)

class Person {
    // 动态代码块不能放在变量之前
    // 无法在字段定义之前使用字段
    {
        System.out.println("动态代码块执行");
        name = "john";
        age = 10;
        System.out.println(name + age); // 报错位置
    }

    String name;
    int age;

    public Person() {
        System.out.println("Person构造器执行");
    }
}
  1. 静态代码块

类加载时,执行静态代码块(仅执行一次)。在静态属性初始化之后执行静态代码块。作用:可为静态属性赋值,或必要的初始化行为。

当类加载时,触发静态代码块的执行,输出china特殊的:如果将country静态变量放在代码块下面,将输出null。可根据反编译代码查到原因。

class Student {
    
    static String country = "china";
   
    static {
        System.out.println(Student.country);
    }

    public void show() {
    
    }
}

对象创建过程各属性和代码块加载顺序:

静态属性 -> 静态代码块 -> 实例属性 -> 动态代码块 -> 构造方法

带有继承的对象创建过程

父类静态属性 -> 父类静态代码块 -> 子类静态属性 -> 子类静态代码块 -> 父类实例属性 -> 父类动态代码块 -> 父类构造方法 -> 子类实例属性 -> 子类实例代码块 -> 子类构造方法

final

final修饰的类不能被继承、属性不能再次修改、方法不能被覆盖。

final可修饰的内容:类、方法、属性。

常见的被final修饰的类:StringMathSystem,均不能被继承。

  • final 变量:「final」修饰基本数据类型,final int num = 10,内容不可变。
  • 实例常量:在类中声明,实例常量的赋值时机:显示初始化、动态代码块、构造方法,但一般都用前两种,因为如果在构造方法中进行赋值时,必须保证所有的构造方法都能对其进行正确赋值。
  • 静态常量:static final String SCHOOL_NAME;,赋值时机:显示初始化、静态代码块。
  • 对象常量:「final」修饰引用数据类型,地址不可变,但内容可变

注意

  • abstractfinal不能同时使用:抽象类或方法就是为了让继承而使用的,增加final又不让继承或覆盖,二者相矛盾。
  • abstractstatic不能同时使用:static直接对方法和属性进行调用,而方法没有方法体,二者相矛盾。