先上测试代码:
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中的四种内部类:实例内部类、局部内部类、匿名类和静态内部类,并通过实例代码进行详细解析。 1. **实例内部类**:这是最常见的内部类形式,它在外部类的实例方法或成员位置定义。实例内部...
14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14.java局部内部类(方法中类).zip14...
java 局部内部类的使用规范 java 局部内部类的使用规范
内部类可以分为四种类型:静态内部类、成员内部类(非静态内部类)、局部内部类和匿名内部类。 1. **静态内部类**: 静态内部类与普通的成员内部类不同,它不持有对外部类的引用。因此,可以像其他静态成员一样,...
- 不同类型的内部类(静态内部类、成员内部类、局部内部类和匿名内部类)的区别和用法 - 内部类的优缺点以及使用场景 这些目标将帮助你理解和掌握内部类的概念,并能够在适当的时候使用内部类来解决问题...
Java 中局部内部类可以访问它所在方法中定义的 final 修饰的局部变量的合理解释 在 Java 中,局部内部类可以访问它所在方法中定义的 final 修饰的局部变量,这是一个非常重要的知识点。这是因为 JVM 在编译时会将 ...
局部内部类和匿名内部类是Java中的一种特性,它们允许我们在方法内部定义类。然而,一个重要的限制是,这些内部类只能访问在其作用域内的final或者实际上等效于final的局部变量。这是因为内部类可能在外部方法结束后...
内部类分为四类:非静态成员内部类、静态成员内部类、局部内部类和匿名内部类。接下来将逐一介绍这四种类型的内部类。 #### 二、非静态成员内部类 非静态成员内部类是最常见的一种内部类形式,它具有以下特点: 1...
Java ---- 局部内部类 静态内部类 普通内部类
Java内部类之局部内部类 Java内部类是一种特殊的类,它可以嵌套在其他类中,今天我们主要介绍Java局部内部类的相关知识,了解局部内部类的定义、特性和使用场景。 什么是局部内部类? 局部内部类是定义在代码块、...
内部类分为几种类型,包括成员内部类、局部内部类、匿名内部类以及方法参数内部类。 1. **成员内部类**:成员内部类就像是外部类的一个普通成员,可以是静态或非静态的。非静态内部类拥有对外部类的引用,可以直接...
- 第6章 面向对象(下)- 6.7 内部类6.7.4 局部内部类什么是局部内部类在方法里定义内部类就是一个局部内部类,局部内部类仅在该方法里有效。由于局部内部
根据不同的应用场景和特性,内部类可以分为多种类型:成员内部类、局部内部类、静态内部类、匿名内部类。下面将详细介绍每种类型的内部类及其特点和使用方法。 #### 成员内部类 成员内部类(也称为非静态内部类)...
2. **局部内部类**:定义在方法内部的类,具有局部变量的特性,不能有静态属性和方法,也不能在类外直接访问。它可以访问外部类的所有成员以及所在方法的final变量。局部内部类主要用于方法内部的特定逻辑,对外不...
2. 局部内部类:在方法中定义的内部类,局部内部类不能有访问说明符,因为它不是外围类的一部分,但是它可以访问当前代码块内的常量,和此外围类所有的成员。 3. 静态内部类:静态内部类是指在外部类的静态成员中...
Java局部内部类是一种特殊的内部类,它是在方法、块或者匿名函数中定义的类,具有非常有限的作用域。这种类型的内部类只能在其被声明的范围内使用,因此它们通常用于实现特定方法的功能,或者处理方法中的复杂逻辑。...
内部类主要分为四种类型:静态内部类、成员内部类、局部内部类和匿名内部类。 1. 静态内部类(Static Inner Class) 静态内部类与普通的类类似,只是它们定义在外部类中,并且前面带有 `static` 关键字。它们不会...
2. **局部内部类**: 定义在方法、构造器或块中的类被称为局部内部类。它的作用范围仅限于该方法、构造器或块。 3. **静态内部类**: 声明为static的内部类,称为静态内部类。它不持有对外部类的隐式引用,因此可以...
方法内部类对象不能使用该内部类所在方法的非final局部变量。 四、匿名内部类 匿名内部类是指不具有名称的内部类。匿名内部类适合使用场景包括:只用到类的一个实例、类在定义后马上用到、类非常小、给类命名并...