先上测试代码:
public class TestCompileConstant {
public static void main(String[] args) {
List list = method2();
Field[] fields = list.getClass().getDeclaredFields();
Constructor[] cons = list.getClass().getDeclaredConstructors();
for(Constructor con:cons){
System.out.println(con.toString());
}
for(Field field:fields){
System.out.println(field.toString());
}
}
static List method2(){
Random ran = new Random();
final int a = ran.nextInt();
final int b = 5;
final int bb = ran.nextInt();
final int[] cc = new int[12];
for (int i = 0; i < cc.length; i++) {
cc = i;
}
System.out.println(a);
return new AbstractList(){
public Object get(int i){
if(i<0||i>=cc.length)
return b;
return cc[i];
}
@Override
public int size() {
switch(2){
case 1:
// case a: //is not compile-time constant
break;
}
int c = bb;
return a;
}
};
}
}
奇怪的地方:
List list = method2();
list.get(1) = 1; //???????
照理说 method2()的返回值list get()方法返回是一个本该失效的局部变量cc,那么是什么使cc能够存活下来呢?
第一天: 粗看int[] 为对象,那么应该存在heap区,当方法结束后,内部类list 中仍有应用所以没有被gc .
问题: int[] 是对象没错,那么换一个基本类型呢?局部变量b一样可以被返回怎么解释?
第二天: b 为一个compile-time constant 即编译时常量,当运行时b是作为literal存在的,即运行时代码应为: if(i<0||i>cc.length) return 5;
问题: 从这个角度似乎能解释问题了,那么运行时常量 a 又如何呢?
第三天: 从测试代码看,a也可以被正常返回,通过查阅资料理解为: jvm处理一个 .class ,将对像放入heap区;具体执行的方法在java栈的java帧中;类的基本信息存放在方法区,其中也包括常量池.故推论,final a 存入常量池,方法结束java帧销毁但与常量无关,故可以被访问.
第四天: 常量池中只有 compile-time constant , 像a这样的运行时常量不在此列,迷茫中...
第五天: 真相大白,局部内部类凡是引用外部的运行时常量,jvm都会自动为其创建一个final field,及一个相应的构造方法. 关于为什么compile-time constant 不需要,请看第二天内容.
这也说明为什么内部类中只能访问外部的final属性,它需要自己也copy一份作为自己的field,而使用final修饰符就不用担心两者的不一致.
具体可见test code 的输出内容,利用反射我们可以得到 list 的内部结构:
test.newTest.TestCompileConstant$2(int,int)
public java.lang.Object test.newTest.TestCompileConstant$2.get(int)
public int test.newTest.TestCompileConstant$2.size()
private final int test.newTest.TestCompileConstant$2.val$bb
private final int test.newTest.TestCompileConstant$2.val$a
over....
分享到:
相关推荐
java 内部类 实例内部类 局部内部类 匿名类 静态内部类 实例代码
14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14...
java 局部内部类的使用规范 java 局部内部类的使用规范
- 不同类型的内部类(静态内部类、成员内部类、局部内部类和匿名内部类)的区别和用法 - 内部类的优缺点以及使用场景 这些目标将帮助你理解和掌握内部类的概念,并能够在适当的时候使用内部类来解决问题...
Java ---- 局部内部类 静态内部类 普通内部类
- 第6章 面向对象(下)- 6.7 内部类6.7.4 局部内部类什么是局部内部类在方法里定义内部类就是一个局部内部类,局部内部类仅在该方法里有效。由于局部内部
day11_11_局部内部类定义
1.接口-简介 2.接口-作用 3.接口-定义方式 4.接口-实现 5.接口-与抽象类之区别 6.接口-应用示例(设计模式...内部类-局部内部类 12.内部类-匿名内部类 13.内部类-静态内部类 14.综述
局部内部类访问外边的局部变量 马克-to-win java视频的介绍
主要介绍了Java局部内部类的相关资料,帮助大家更好的理解和学习Java 内部类的知识,感兴趣的朋友可以了解下
Java语言中的内部类根据定义的位置和访问权限可以分为四类:成员内部类、局部内部类、匿名内部类和静态内部类。成员内部类是定义在类的内部且与类的实例相关联的类;局部内部类是定义在方法或作用域内的类;匿名内部...
day11_12_局部内部类的final问题
成员内部类、局部内部类、静态内部类、匿名内部类
NULL 博文链接:https://jayxigua.iteye.com/blog/686371
主要介绍了Java局部内部类原理与用法,结合实例形式分析了Java局部内部类功能、用法及相关操作注意事项,需要的朋友可以参考下
Java基础精品课14-常用类1录屏5.局部内部类.mp4
局部内部类 Local inner 马克-to-win java视频的详细介绍
//从阅读角度,这里预期打印a=20,然而只会打印出a=10,会让人误解,因为在Inner的change()中修改的是Inner内部类对象的this.a,它是m
主要介绍了Java局部内部类和匿名内部类,结合实例形式分析了java局部内部类和匿名内部类相关定义、原理与用法,需要的朋友可以参考下