A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 余海龙 黑马帝   /  2012-2-9 14:35  /  2306 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 余海龙 于 2012-2-10 18:58 编辑

public class Exercise3 {

        public static void main(String[] args) {
                Frame frame = new Frame("练习3");
                frame.setSize(600, 400);
                frame.setLocation(200, 200);
                frame.setLayout(new FlowLayout());
       
                frame.addWindowListener(new WindowAdapter() {
                        public void windowClosing(WindowEvent e) {
                                frame.dispose();   // 编译报错“不能引用另一方法中定义的内部类中非终态变量 frame”
                        }
                });

                frame.setVisible(true);   
        }

}

frame.dispose();  
这句话编译报错说:“不能引用另一方法中定义的内部类中非终态变量 frame”
大家帮忙解释一下,为什么Frame frame = new Frame("练习3");前面需要加final ,谢谢!

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

4 个回复

倒序浏览
内部类的访问规则:
1,内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式 外部类名.this
2,外部类要访问内部类,必须建立内部类对象。

内部类定义在局部时,
1,不可以被成员修饰符修饰
2,可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量。只能访问被final修饰的局部变量。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
在内部类中调用frame.dispose(); 不会对frame的造成影响,因为他是局部的,所以要加上final修饰符。
Java对匿名内部类的实现是通过编译器来支持的,即通过编译器帮我们产生一个匿名类的类名,将所有在匿名类中用到的局部变量和参数做为内部类的final字段,同是内部类还会引用外部类的实例。为什么引用外部类的字段却是可以不用final修饰的呢?这是因为内部类保存了外部类的引用,因而内部类中对任何字段的修改都回真实的反应到外部类实例本身上,所以不需要用final来修饰它。

评分

参与人数 1技术分 +1 收起 理由
admin + 1

查看全部评分

回复 使用道具 举报
      Listener中的windowClosing 被调用时,内部类所在的函数早就执行完了,此时外部类局部变量frame ,有可能不存在了,如果没有final的话,那么内部类使用的外部类局部变量要用哪个值呢?无final 修饰,局部变量的生命周期,比内部类的短,有可能这样:一个方法已结束,局部变量已消毁,但里面的内部类还在。
  定义为final后,内部类访问final型局部变量时,由于final---其值永不变,因而内部类照样可以访问final型局部变量。对于上面的frame ,如不是final,可以在后面加一句:frame = new Frame("练习4"),这样当windowClosing时,就不知道关闭那个frame 了,而此时main 方法已执行完了。
回复 使用道具 举报
以前坛里也有:从内部类访问局部变量,局部变量需要被声明为final,为什么?
以下是来自网上的解释,通俗易懂:

1)所谓“局部内部类”就是在对象的方法成员内部定义的类。而方法中的类,访问同一个方法中的局部变量,是天经地义的。那么为什么要加上一个final呢?
2)原因是:编译程序实现上的困难,难在何处:内部类对象的生命周期会超过局部变量的生命期。为什么?表现在:局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建(诞生),当方法调用结束时(执行完毕),退栈,这些局部变量全部死亡。而:内部类对象生命期,与其它类一样,当创建一个该局部类对象后,只有没有其它人再引用它时,它才能死亡。完全可能:一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量。
3)退一万步:局部类的对象生命期会超过局部变量又怎样?问题的真正核心是:如果:局部内部类的对象访问同一个方法中的局部变量,是天经地义的,那么:只要局部内部类对象还活着,则:栈中的那些它要访问的局部变量就不能“死亡”(否则:它都死了,还访问个什么呢?),这就是说:局部变量的生命期至少等于或大于局部内部类对象的生命期。而:正是这一点是不可能做到的
4)但是从理论上:局部内部类的对象访问同一个方法中的局部变量,是天经地义的。所以:经过努力,达到一个折中结果:即:局部内部类的对象可以访问同一个方法中的局部变量,只要这个变量被定义为final.那么:为什么定义为final变可以呢?定义为final后,编译程序就好实现了:具体实现方法是:将所有的局部内部类对象要访问的final型局部变量,变成该内部类对象中的一个数据成员。这样,即使栈中局部变量(含final)已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量。

归纳上述回答的真正核心是:局部内部类对象中包含有要访问的final型局部变量的一个拷贝,成为它的数据成员。因此,正是在这个意义上,final型局部变量的生命期,超过其方法的一次调用。严格来说,方法调用结束,所有的局部变量(含final)全死亡了。但:局部内部类对象中有final型局部变量的拷贝。

评分

参与人数 1技术分 +2 收起 理由
admin + 2 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马