今天通过代码了解外部类和内部类加载时机的时候,发现了一个问题就是在外部类中调用内部类的final修饰的静态变量的时候发现有时候内部类的静态代码块没有执行,在网上查询了相关的信息,结果还是一头雾水,后来无意间看了一下生成的class文件我才恍然大明白,下面直接上代码:
java文件:
public class OutClass { public static void b(){ System.out.println("--b--"); String interStr = InterClass.interStr; String interStr_no_final = InterClass.interStr_no_final; int num = InterClass.num; Integer numInteger = InterClass.numInteger; Date date = InterClass.date; } public static void main(String[] args) { OutClass.b(); } public static class InterClass{ static { System.out.println("--inter--"); } private static final String interStr = "interStr"; private static String interStr_no_final = "interStr_no_final"; private static final Date date = new Date(); public static final Integer numInteger = 1; public static final int num = 1; } }
class文件:
public class OutClass { public OutClass() { } public static void b() { System.out.println("--b--"); String interStr = "interStr"; String interStr_no_final = OutClass.InterClass.interStr_no_final; int num = true; Integer numInteger = OutClass.InterClass.numInteger; Date date = OutClass.InterClass.date; } public static void main(String[] args) { b(); } public static class InterClass { private static final String interStr = "interStr"; private static String interStr_no_final; private static final Date date; public static final Integer numInteger; public static final int num = 1; public InterClass() { } static { System.out.println("--inter--"); interStr_no_final = "interStr_no_final"; date = new Date(); numInteger = 1; } } }
通过对比编译前后生成的代码大家不难发现,内部类中的基本数据类型或String类型的静态变量被final修饰时,经过编译生成的class文件中对应赋值代码并没有发生变化,并且外部类对应的代码位置都已经变成了对应的变量值,也就是说经过编译后的外部类已经不再依赖内部类,所以如果只调用这些静态变量,内部类的静态代码块将不会执行,而剩余的静态变量的赋值语句都被转移到了内部类的静态代码块中了,如果外部类调用内部类相应静态变量进行赋值操作就必须执行内部类的静态代码块才能为对应的静态变量进行赋值从而达到赋值的目的。