日期:2014-05-20  浏览次数:20742 次

匿名内部类使用final参数的问题
Java code
 package test;
public class TestFinal 
{
    //只有定义成 final User user 才不会报错为什么?
    public void test( User user)
    {
        (new Thread()
            { 
                public void run()
                    {   
                        System.out.println("user.name-->"+user.name);
                    }
            } 
        ).start();  
    }
    public static void main(String[] args) 
    {
        User user=new User();
        user.setId(007);
        user.setName("zhaoyang");
        
        TestFinal testFinal=new TestFinal();
        testFinal.test(user);    
    }
}


class  User
{
    String name=null;
    int id;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    
}


------解决方案--------------------
引用楼主 zhaoyangjay 的帖子:
Java code package test;
public class TestFinal
{
//只有定义成 final User user 才不会报错为什么?
public void test( User user)
{
(new Thread()
{
public void run()
{
System.out.println("user.name-->"+user.name);
}
}
).start();
}
public s…

------解决方案--------------------
6的理由很牵强了。
“当变量是final时,通过将final局部变量"复制"一份”
这不是final的理由,因为从编译实现上,当普通局部变量传给匿名类的时候同样可以“复制”。
其实就是传给匿名类的构造方法,使方法中的局部变量和匿名类中同时拥有这个对象的引用。


但真正的原因就在这里,当外面的方法重新赋值的时候,不影响内部类的句柄指向那个对象,
即外部的变量指向A而匿名类的变量却指向B了,这才是不能接受的结果。
因为从源程序上看它们是同一变量。
------解决方案--------------------
你的回答完全是因果倒置的。
如何实现?
要保证内部类访问外部的方法的局部变量时生命周期,在实现时必须使内部类也持有对那个外部方法中局部变量的引用(复制这个词太含糊),也就是在内部类的方法中也要有一个句柄指向那个对象,这样当外部的方法退出后,内部类自己的句柄还指向那个对象,所以不会被回收。

因为这个原因,才需要final的定义来保证外部方法中的那个句柄和内部类的句柄指向的对象是同一的,否则两者任一重新赋值,都会造成它们指向不同的对象。而不是“当变量是final时将变量复制”


不是因为是final就会复制,是因为需要复制才需要final!