Java类初始化

Java类和接口的初始化

一个类或者接口T将会初始化在以下方式第一次发生

  1. T是一个类,生成一个T的实例
  2. T所声明的一个静态方法被调用 getDeclaredMethod
  3. T所声明的一个静态作用域被分配 getDeclaredField
  4. T所声明的一个静态作用域被使用,并且该作用域不是一个常量

Final Variables

一个final变量只能够被赋值一个。如果final指向一个对象的话,引用不可变,对象的值可以发生变化。

blank final 指一个未经初始化的final 变量

constant final 指的是经过常量表达式constant expression初始化的Java 原始数据类型或者String类型

//Java原始数据类型 primitive type
boolean ,byte,char,int,short,float,long,double
//String是引用类型

Constant Expression

  • Literals of primitive type and literals of type String 直接常量
  • Casts to primitive types and casts to type String 基本类型或String类型转换
  • The unary operators +, -, ~, and ! (but not ++ or –) 一元操作符,如+8、-10
  • The multiplicative operators *, /, and % 乘、除以及取模运算
  • The additive operators + and - 加减运算
  • The shift operators <<, >>, and >>> 移位
  • The relational operators <, <=, >, and >= 关系操作
  • The equality operators == and != 等值运算
  • The bitwise and logical operators &, ^, and | 位和逻辑运算
  • The conditional-and operator && and the conditional-or operator || 条件与和条件或操作
  • The ternary conditional operator ? : 三元条件操作
  • Parenthesized expressions whose contained expression is a constant
    expression 加上括号的常量表达式
  • Simple names that refer to constant variables
  • Qualified names of the form TypeName . Identifier that refer to
    constant variables

测试

1. 接口初始化

public class Assign {
    public static int assignAndPrint(String name, int i) {
        System.out.println(name + "=" + i);
        return i;
    }
}
public interface SuperInterface{
    //接口中作用域默认都是public static final
    int i = 2; //常量
    int j = Assign.assignAndPrint("SuperInterface.j", 10);//blank final
}

public interface SubInterface extends SuperInterface{
    int a = Assign.assignAndPrint("SubInterface.a", 10);
}
public class ClassInitialize {
    public static void main(String[] args) {
        //无初始化-作用域i在父接口中,属于常量,访问时不初始化
        System.out.println(SubInterface.i);

        //初始化SuperInterface-作用域j在SuperInterface中,将初始化SuperInterface
        System.out.println(SubInterface.j);

        //初始化SubInterface
        System.out.println(SubInterface.a);


    }
}
//通过子类使用父类的静态作用域,不会初始化子类,父类是否初始化,要看该作用域是否为常量

2. 类初始化

public class SuperClass {
    public static int i = 2;
    public static final int finalI = 3;
    public static int j = Assign.assignAndPrint("SuperClass.j", 10);
    public static int k = Assign.assignAndPrint("SuperClass.k", 100);
}

public class SubClass extends SuperClass{
    public static int a = Assign.assignAndPrint("SubClass.a", 10);
}
//1
System.out.println(SubClass.a); //子类初始化,但须先初始化父类(这点和接口不一样)
/*Output:
SuperClass.j=10
SuperClass.k=100
SubClass.a=10
10
*/

//2
System.out.println(SubClass.i); //调用父类中非常量,只初始化父类
/*Output:
SuperClass.j=10
SuperClass.k=100
2
*/

//3
System.out.println(SubClass.finalI);//调用父类中常量,不初始化
/*Output:
3
*/

//4
System.out.println(SubClass.j); //相当于给静态作用域赋值,初始化父类
/*Output:
SuperClass.j=10
SuperClass.k=100
10
*/

总结

  1. 静态方法被调用静态作用域被赋值非常量的作用域的使用会引起方法或作用域所在的类或接口被初始化。
  2. 子类初始化时会先初始化父类,但子接口不会初始化父接口

参考文献

Java编程规范 12.4节 Initialization of Classes and Interfaces http://docs.oracle.com/javase/specs/jls/se8/jls8.pdf

你可能感兴趣的:(Java)