类的使用方式
类的初始化:JVM只会在 “首次主动使用” 一个类/接口时,才会初始化它们。
主动使用
通过 new 构造类的实例
package init;
class Test{
    static {
        System.out.println("test static ...");
    }
}
public class run {
    public static void main(String[] args) {
        new Test();	//首次主动使用
        new Test();
    }
}
static 代码块会在类初始化时自动加载,如果以上代码输出了 test1 static ... 说明 test1 类被初始化了。
以上代码 new 了两次 Test1 对象,但是只打印了一次,因为只有在首次使用时,才会初始化该类。
访问类/接口的静态成员(属性,方法)
package init;
class Test{
	static {
		System.out.println("test static ...");
	}
	
	static int i = 10;
	
	static void testMethod() {
		System.err.println("test static testMethod .....");
	}
	
}
public class run {
	public static void main(String[] args) {
//		Test.i = 1;
//		System.err.println(Test.i);
		
		Test.testMethod();
	}
}
特殊情况
- 
如果成员变量即是 static又是final, 即常量,则不会被初始化!
- 
上一种情况中,如果常量的值是一个 随机值,则又会被初始化。 package init; class Test{ static final int i = (int)(Math.random() * 1000); static { System.err.println("test static ......"); } } public class run { public static void main(String[] args) { System.err.println(Test.i); } }
反射使用的类
package init;
class Test{
	static {
		System.out.println("test static ...");
	}
}
public class run {
	public static void main(String[] args) throws Exception {
		
		 Class.forName("init.Test");
		 
		 new Test().getClass();
		 
		 /** 上面两种可以初始化,下面的不行 */
		 
		 Test.class.getClass();
	}
}
初始化一个子类时,该子类的父类也会被初始化
package init;
public class Father {
	static {
		System.err.println("father static .....");
	}
	
}
package init;
public class son extends Father{
	static {
		System.err.println("son static ......");
	}
}
package init;
public class run {
	public static void main(String[] args){
		new son();
	}
}
结果:
father static .....
son static ......
动态语言
动态语言在执行过程中所涉及的类,也会被初始化(动态代理)
被动使用
除了主动使用以外,其他都是被动使用
package init;
class Test{
	static {
		System.err.println("test static ......");
	}
}
public class Test4 {
	public static void main(String[] args) {
		Test[] t = new Test[4];
	}
}
通过数组定义引用类,为类的被动使用,不会触发该类的初始化。
探究
为什么调用静态常量不会初始化类
class Test {
    /**
     * final static 称为常量
     * 常量产生的时机:
     *      时间: 编译期间
     *      地点: (调用这个常量的方法 所在类[Run]的常量池)常量池
     */
    final static int i = 10;
    static {
        System.out.println("test static .....");
    }
}
/**
 * Run的常量池中保存了Test中产生的常量[i = 10]
 */
public class Run {
    public static void main(String[] args) {
        System.err.println(Test.i);
    }
}
通过查看 Run 类的 class 文件后发现,输入语句直接输出了10,与 Test 中的 10 没有任何关系。
public class Run {
    public Run() {
    }
    public static void main(String[] args) {
        System.err.println(10);
    }
}
    If you’re going to reuse code, you need to understand that code!

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号