上一节对静态属性的所属类的初始化进行了分析,本小节将对
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
System.out.println(FinalPojo.str);
}
}
class FinalPojo{
public final static String str="FinalPojo field";
static {
System.out.println("FinalPojo Initialization");
}
}
输出结果为:
FinalPojo field
Process finished with exit code 0
首先分析,如果说不加final的情况,类会被初始化,FinalPojo Initialization会被打印出来,但是加了final之后,FinalPojo没有被初始化,这个时候就有一个问题出现了,为什么会是这样的一个结果那?
现在公布答案,这个结果和final有着极其重要的关系;
现在删除掉FinalPojo.class文件,验证下是否失败。
运行代码输出结果为:
FinalPojo field
Process finished with exit code 0
点开MyTest1.class文件,常量直接在编译出来的文件中了已经,不需要再去源文件中获取常量信息
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
System.out.println(FinalPojo.str);
}
}
class FinalPojo{
public final static String str= UUID.randomUUID().toString();
static {
System.out.println("FinalPojo Initialization");
}
}
如果常量编译期无法确定,那么会在运行期调用常量;
代码运行结果为:
FinalPojo Initialization
a53e3b9c-e601-4338-9ac8-7b5e604b2686
Process finished with exit code 0
每一个常量的值并不是编译期间可以确定的,那么其值不会放到被调用类的常量池中,这时在程序运行时,会导致主动使用这个常量所在的类,显然回到这个类会被初始化。
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
System.out.println(FinalPojo.str);
}
}
class FinalPojo{
// public final static String str= UUID.randomUUID().toString();
public final static String str="123456";
public static int i=1;
public static int x=128;
public static int y=127;
public static short z=127;
static {
System.out.println("FinalPojo Initialization");
}
}
代码编译完成,通过javap反编译指令查看字节码文件FinalPojo.class;
com.mfhcd.jvm.chapter_1.webnesday.FinalPojo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
static {
};
Code:
0: iconst_1
1: putstatic #2 // Field i:I
4: sipush 128
7: putstatic #3 // Field x:I
10: bipush 127
12: putstatic #4 // Field y:I
15: bipush 127
17: putstatic #5 // Field z:S
20: getstatic #6 // Field java/lang/System.out:Ljava/io/PrintStream;
23: ldc #7 // String FinalPojo Initialization
25: invokevirtual #8 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
28: return
}
static {};静态代码块之前就不多说了,后面会多这部分进行补充。主要是初始化过程中都做了哪些事情?当然需要把助记符给大家介绍一下:
助记符
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
FinalPojo[] finalPojos=new FinalPojo[1];
}
}
class FinalPojo{
static {
System.out.println("FinalPojo Initialization");
}
}
输出结果为:
Process finished with exit code 0
FinalPojo类并没有初始化;
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
FinalPojo[] finalPojos=new FinalPojo[1];
System.out.println(finalPojos.getClass());
System.out.println(finalPojos.getClass().getSuperclass());
}
}
class FinalPojo{
static {
System.out.println("FinalPojo Initialization");
}
}
对应数组实例来说,其类型是由jvm在运行期动态生成的,表示[Lcom.mfhcd.jvm.chapter_1.webnesday.FinalPojo;
这种形式,动态生成的类型,其父类就是Object;
对于数组来说,JavaDoc经常将构成数组的元素为Component,实际上就是将数组降低一个维度后的类型(不在是类本身)
这里介绍下jvm中数组是如何表示的例如上面的[L表示any non-primitives(Object),翻译过来为任何非基元(对象)也就是非基本类型的对象[引用类型]
/**
* @author lijk
* @date 2019/12/25 16:55
*/
public class MyTest1 {
public static void main(String[] args) {
FinalPojo[] finalPojos=new FinalPojo[1];
System.out.println(finalPojos.getClass());
int[] i=new int[1];
System.out.println(i.getClass());
short[] s=new short[1];
System.out.println(s.getClass());
double[] d=new double[1];
System.out.println(d.getClass());
}
}
class FinalPojo{
static {
System.out.println("FinalPojo Initialization");
}
}
输出结果为:
class [Lcom.mfhcd.jvm.chapter_1.webnesday.FinalPojo;
class [I
class [S
class [D
Process finished with exit code 0
以上就是引用类型数组和基本类型数组的总结分析,如果有不正确的地方,还是需要读者指正的,感谢万分…