Loading

类的使用方式

类的初始化: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!
posted @ 2021-02-12 22:43  不颓废青年  阅读(55)  评论(0编辑  收藏  举报