黑马程序员技术交流社区
标题:
为何匿名内部类访问外部变量要用final
[打印本页]
作者:
沙漠里的小鱼
时间:
2013-2-17 01:23
标题:
为何匿名内部类访问外部变量要用final
为何匿名内部类访问外部变量要用final
作者:
罗正荣
时间:
2013-2-17 01:45
是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的作用域只在这个方法内部有效。因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用。
作者:
Gaara
时间:
2013-2-17 01:56
楼上说的好,学习了....
作者:
孙含庆
时间:
2013-2-17 03:23
生命周期问题,外部变量存在于栈内存中,他可能随着方法的执行后就已不在存在,不存在的话,内部类访问这个不存在的变量就会出错,
作者:
逍林游
时间:
2013-2-17 09:26
二楼的很详细,学习···
作者:
王亚东
时间:
2013-2-17 09:38
package bao01.io;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
public class T08_MergerIO {
// 获得Enumera对象
public Enumeration<FileInputStream> getEn() throws IOException {
ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
for (int i = 1; i <= 3; i++) {
al.add(new FileInputStream("d:\\" + i + ".part")); // 假如d盘下有1.part、2.part、3.part三个文件
}
final Iterator<FileInputStream> iterator = al.iterator();
for (; iterator.hasNext();) {
System.out.println(iterator.next());
}
Enumeration<FileInputStream> en = new Enumeration<FileInputStream>() {
@Override
public FileInputStream nextElement() {
return iterator.next();
}
public boolean hasMoreElements() {
return iterator.hasNext();
}
};
return null;
}
public static void main(String[] args) throws IOException {
T08_MergerIO t = new T08_MergerIO();
t.getEn(); // 如果iterator不被final修饰,第一次调用iterator被初始化,匿名类中的iterator也是这个iterator
Enumeration<FileInputStream> en = t.getEn(); //第二次iterator将被重置。而匿名类中的iterator原本指向的堆中的值将失去引用,
//从而被垃圾回收机制清理。当在下面的代码中使用的时候,就会出现不可预知的错误。
// SequenceInputStream sis = new SequenceInputStream(en);
//另:被final修饰的变量 会比普通变量有更长的生命周期。
//注:我是在看黑马程序员基础视频IO——3第20天17讲遇到的这个问题,查了下资料,个人理解至此,希望对大家有所帮助。
//另2:方法中的匿名类,在方法被多次调用时,此类会不会被多次编译?不会?
}
}
复制代码
作者:
黄玉昆
时间:
2013-2-17 11:02
我查了查相关资料,理解如下:在java中,方法是一种状态,是不能被存储的,对象才是真正被存储在堆内存中的。匿名内部类是在内部,是局部的,它所处的外部环境即方法,在执行完后就不存在了,但是内部类作为一个对象,是有可能被存储下来的。而局部变量也是如此,局部变量时存在于栈内存中的,使用完了就立即被消灭掉了,而匿名内部类访问局部变量,也是对它的一个拷贝而已;那么试想,局部变量都没了,匿名内部类还存在,这个匿名内部类要去哪找这个变量啊,她找不到局部变量这孩子,多着急,只能让虚拟机报警了(编译失败)。所以就要将这个局部变量变为永久的常量才行。
作者:
炉海佳
时间:
2013-2-17 15:16
学习了----
作者:
郭冰川
时间:
2013-2-17 15:41
学习了
作者:
李洪因
时间:
2013-2-17 20:19
如果定义一个匿名内部类,并且希望它使用一个在其外部定的对象,那么编译器会要求其参数引用是final 的。Java虚拟机的实现方式是,编译器会探测局部内部类中是否有直接使用外部定义变量的情况,如果有访问就会定义一个同类型的变量,然后在构造方法中用外部变量给自己定义的变量赋值。
interface aa
{
public void print();
}
public class ww
{
String string="aaaa"; //这里不需要定义final
public static void main(String[] args)
{
}
public void bb()
{
final String string1="bbbb";//这里需要定义为final
aa a1=new aa()
{
public void print()
{
System.out.println(string);
System.out.println(string1);
}
};
}
}
作者:
刘军亭
时间:
2013-2-17 20:36
沙发正解
作者:
冯飞
时间:
2013-2-20 18:17
.匿名内部类为什么只能用final.是变量的作用域的问题,因为匿名内部类是出现在一个方法的内部的,如果它要访问这个方法的参数或者方法中定义的变量,则这些参数和变量必须被修饰为final。因为虽然匿名内部类在方法的内部,但实际编译的时候,内部类编译成Outer.Inner,这说明内部类所处的位置和外部类中的方法处在同一个等级上,外部类中的方法中的变量或参数只是方法的局部变量,这些变量或参数的作用域只在这个方法内部有效。因为编译的时候内部类和方法在同一级别上,所以方法中的变量或参数只有为final,内部类才可以引用。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2