今天看了单例模式,对内部类的加载顺序产生了疑问。所以来请教大家。
我们知道,java当中,类的加载顺序是:类静态块-类静态属性-类内部属性-类构造方法。
但是当有内部类的时候会怎样呢?我们先看一下代码。
public class Singleton {
public static class Inner{
static {
System.out.println("TestInner Static!");
}
public final static Singleton testInstance = new Singleton(3);
}
public static Singleton getInstance(){
return Inner.testInstance;
}
public Singleton(int i ) {
System.out.println("Test " + i +" Construct! ");
}
//类静态块
static {
System.out.println("Test Static");
}
//类静态属性
public static Singleton testOut = new Singleton(1);
public static void main(String args[]){
Singleton t = new Singleton(2);
Singleton.getInstance();
}
}
Test Static
Test 1 Construct!
Test 2 Construct!
TestInner Static!
Test 3 Construct!
public class Singleton {
public static class Inner{
public final static Singleton testInstance = new Singleton(3);
static {
System.out.println("TestInner Static!");
}
}
public static Singleton getInstance(){
return Inner.testInstance;
}
public Singleton(int i ) {
System.out.println("Test " + i +" Construct! ");
}
//类静态块
static {
System.out.println("Test Static");
}
//类静态属性
public static Singleton testOut = new Singleton(1);
public static void main(String args[]){
Singleton t = new Singleton(2);
Singleton.getInstance();
}
}
输出为:
Test Static
Test 1 Construct!
Test 2 Construct!
Test 3 Construct!
TestInner Static!
对jvm的内部机制不清楚,所以来请教大家。万分感谢。
这种问题应该能百度到吧。。。我碰到这种地方会去百度 一般都不会同时用到这些
一般好像也不会用到public的静态内部类
其实没必要搞那么明白 平时用不到的东西 过一段时间你又会搞混了或者搞忘了 需要用就查资料
有规律的,你这还不算复杂,如果包含父类以及内部类(非静态)就更复查,但是万变不离其宗。
规律一、初始化构造时,先父后子;只有在父类所有都构造完后子类才被初始化
规律二、类加载先是静态、后非静态、最后是构造函数
静态构造块、静态类属性按出现在类定义里面的先后顺序初始化,同理非静态的也是一样的,只是静态的只在加载字节码是执行一次,不管你new多少次,非静态会在new多少次就执行多少次
规律三、java中的类只有在被用到的时候才会被加载
规律四、java类只有在类字节码被加载后才可以被构造成对象实例
上面四条规律就解析你上面不能理解代码执行结果的原因了
--- 共有 3 条评论 ---类静态块-类静态属性-类内部属性-类构造方法。这个不正确
顺序是:父类静态属性-》父类静态代码块-》子类静态变量-》子类静态代码块-》父类非静态变量-》父类非静态代码块-》父类构造函数-》子类非静态变量-》子类非静态代码块-》-》子类构造函数
这样的加载顺序不是绝对的 因为静态变量和静态代码块跟声明顺序有关。
对于如果静态代码块中调用静态变量,那么静态变量必须在静态代码块前面声明;如果静态代码块中没有调用静态变量,那么就跟顺序有关了,谁先声明谁先被加载。说白了还是顺序加载,之所以会出现“如果静态代码块中调用静态变量,那么静态变量必须在静态代码块前面声明”,是因为变量是声明,所以出现编译错误。
应用到内部类中 静态变量和静态代码块跟声明顺序有关。 这样就可以解释你的问题了。内部类也是类。
测试所用jdk版本1.8.0_20
类静态块-类静态属性这个跟顺序有关系 如果类静态属性在类静态代码块之前 那么类静态属性先初始化
package cn.canon.Single;
public class StaticInnerClassLoaderTime {
public static class Inner {
static {
System.out.println("TestInner Static!");
}
public final static StaticInnerClassLoaderTime testInstance =
new StaticInnerClassLoaderTime(3);
}
public static StaticInnerClassLoaderTime getInstance() {
return Inner.testInstance;
}
public StaticInnerClassLoaderTime(int i) {
System.out.println("Test " + i + " Construct! ");
}
// 类静态属性
public static StaticInnerClassLoaderTime testOut =
new StaticInnerClassLoaderTime(1);
public static int value = 3;
// 类静态块
static {
System.out.println("Test Static" + value);
}
public static void main(String args[]) {
StaticInnerClassLoaderTime t = new StaticInnerClassLoaderTime(2);
StaticInnerClassLoaderTime.getInstance();
}
}
Test 1 Construct!
Test Static3
Test 2 Construct!
TestInner Static!
Test 3 Construct!