通过类字面常量解释接口常量为什么只能定义为static final 类加载过程---Thinking in java

               

   曾经被一哥们问题个问题,为什么接口的常量只能定义为static final,我当时还说他一个接口你定义点方法就行了,还弄什么常量,不过话又说回来,我确实没有解决他的这个问题,以前看Thinking in java貌似解决了类初始化为对象的过程,今天看了一下CLass的类字节变量,感觉又明白许多,下面将代码贴上,逐个分析

package com.bird.thinking;import java.util.Random;/** * @use 探寻Java的Class类内幕 * @author bird * */class Initablepublic static final int staticFinal = 47;//他的值不变 public static final int staticFinal2 = //他的值是变化的  ClassInitialization.rand.nextInt(1000); static {  System.out.println("初始化 Initable"); }}class Initable2public static int stationNonFinal = 147;//注意没有final static{  System.out.println("初始化 Initable2"); }}class Initable3public static int staticNonFinal = 74static{  System.out.println("初始化 Intiable3"); }}public class ClassInitialization public static Random rand = new Random(47); @SuppressWarnings("unchecked"public static void main(String [] args) throws ClassNotFoundException{  @SuppressWarnings("unused")  Class initable = Initable.class;//只是加载字节码进入虚拟机,获得引用没有初始化  System.out.println("After creating Initable ref");  System.out.println(Initable.staticFinal);//请求访问static final定值  System.out.println(Initable.staticFinal2);//请求访问static final 为直接定义的值    System.out.println(Initable2.stationNonFinal);//访问static的值    @SuppressWarnings("unused")  Class initable3 = Class.forName("com.bird.thinking.Initable3");//装载并且初始化  System.out.println("After creating Initable3 ref");  System.out.println(Initable3.staticNonFinal); }}

运行结果如下

After creating Initable ref47初始化 Initable258初始化 Initable2147初始化 Intiable3After creating Initable3 ref74


1.首先说一下第39行,他的意思是仅仅使用Class的方法将


Initable.java的字节码装载到虚拟机中,得到对类的引用,并不初


始化类,更不可能执行static代码块


2.加载完字节码后,直接访问Initable的static final常量,没有任何


问题,说明虽然类没有被初始化,但是static final常量已经可以被


访问(这个是解释接口的重点)



3.当访问Initable的在编译时候没有指定值的static final常量的时


候,他就不能直接访问,看运行结果可知道,他需要初始化类,


即调用static静态代码块,才可以使用.



4.当调用Initable2的static变量的时候,类就必须被执行初始化才能


被访问

5.当调用Class.Forname()方法的时候,将类装载进入虚拟机,就


果断执行了static代码块,初始化后才能继续访问.



6.因此总结一下,一个类的初始化准备工作如下


6.1加载:这个由类加载器完成,他去查找字节码,并且创建一个


Class对象


6.2连接:验证类中的字节码,为静态域分配存储空间,并且如果


必须的话,将解析这个类创建的对其他类的引用


6.3初始化:如果这个类有超类,则对其进行初始化,执行静态初


始化器和静态初始化代码块


6.4初始化被延迟到了对静态方法(构造器是隐士的静态方法)或


非静态方法的首次引用才执行


7.由上面可以知道,接口不能被初始化,如果想定义常量,必须是


在接口的字节码被装载到虚拟机的时候他的常量就得被访问,所

以他必须是static final的


8static final叫编译期常量,不需要初始化就能读取。

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/qq_43679366/article/details/87086408