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

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

[java]  view plain copy print ?
  1. package com.bird.thinking;  
  2.   
  3. import java.util.Random;  
  4.   
  5. /** 
  6.  * @use 探寻Java的Class类内幕 
  7.  * @author bird 
  8.  * 
  9.  */  
  10.   
  11. class Initable{  
  12.     public static final int staticFinal = 47;//他的值不变  
  13.     public static final int staticFinal2 = //他的值是变化的  
  14.         ClassInitialization.rand.nextInt(1000);  
  15.     static {  
  16.         System.out.println("初始化 Initable");  
  17.     }  
  18. }  
  19.   
  20. class Initable2{  
  21.     public static int stationNonFinal = 147;//注意没有final  
  22.     static{  
  23.         System.out.println("初始化 Initable2");  
  24.     }  
  25. }  
  26.   
  27. class Initable3{  
  28.     public static int staticNonFinal = 74;  
  29.     static{  
  30.         System.out.println("初始化 Intiable3");  
  31.     }  
  32. }  
  33.   
  34. public class ClassInitialization {  
  35.     public static Random rand = new Random(47);  
  36.     @SuppressWarnings("unchecked")  
  37.     public static void main(String [] args) throws ClassNotFoundException{  
  38.         @SuppressWarnings("unused")  
  39.         Class initable = Initable.class;//只是加载字节码进入虚拟机,获得引用没有初始化  
  40.         System.out.println("After creating Initable ref");  
  41.         System.out.println(Initable.staticFinal);//请求访问static final定值  
  42.         System.out.println(Initable.staticFinal2);//请求访问static final 为直接定义的值  
  43.           
  44.         System.out.println(Initable2.stationNonFinal);//访问static的值  
  45.           
  46.         @SuppressWarnings("unused")  
  47.         Class initable3 = Class.forName("com.bird.thinking.Initable3");//装载并且初始化  
  48.         System.out.println("After creating Initable3 ref");  
  49.         System.out.println(Initable3.staticNonFinal);  
  50.     }  
  51. }  

运行结果如下

[java]  view plain copy print ?
  1. After creating Initable ref  
  2. 47  
  3. 初始化 Initable  
  4. 258  
  5. 初始化 Initable2  
  6. 147  
  7. 初始化 Intiable3  
  8. After creating Initable3 ref  
  9. 74  


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叫编译期常量,不需要初始化就能读取。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值