`
AutomaticThoughts
  • 浏览: 162408 次
社区版块
存档分类
最新评论

为什么匿名内部类只能访问其所在方法中的final变量

    博客分类:
  • Java
阅读更多

(1).内部类是外部类的一个成员,就像外部类的成员方法一样,所以内部类有权限访问外部类的所有成员,包括private的。
(2).内部类不能访问外部类方法中的局部变量,除非变量是final的(一般发生在方法中定义的内部类)。这是因为局部变量的生命周期原因。

class Outer{
    private int a;
    public class Inner{
        private int a;
        public void method(int a){
            a++;    //局部变量
            this.a++;    //Inner类变量
            Outer.this.a++;    //Outer类变量

        }
    }
}

一般做法是在Outer中写一个返回Inner类对象的方法
public Inner getInner(){
    return new Inner();
}

在其他类中使用内部类:
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
或者 Outer.Inner inner = outer.getInner();

static内部类的使用:
Outer.Inner inner = new Outer.Inner();

(1).所谓“局部内部类”就是在对象的方法成员内部定义的类。而方法中的类,访问同一个方法中的局部变量,却必须要加上一个final。
(2).原因是编译程序实现上的困难:内部类对象的生命周期会超过局部变量的生命期。局部变量的生命期:当该方法被调用时,该方法中的局部变量在栈中被创建,当方法调用结束时,退栈,这些局部变量全部死亡。而内部类对象生命期,与其它类一样,当创建一个局部内部类对象后,只有当没有其它人再引用它时,它才能死亡。所以完全可能一个方法已调用结束(局部变量已死亡),但该局部类的对象仍然活着。即:局部类的对象生命期会超过局部变量。
(3).局部内部类的对象访问同一个方法中的局部变量,那么这就要求只要局部内部类对象还活着,那么栈中的那些它要访问的局部变量就不能“死亡”(否则:它都死了,还访问个什么呢?)。这就是说:局部变量的生命期至少等于或大于局部内部类对象的生命期。
(4).解决方法:局部内部类的对象可以访问同一个方法中被定义为final的局部变量。定义为final后,编译程序的实现方法:将所有的局部内部类对象要访问的final型局部变量,都拷贝成为该内部类对象中的一个数据成员。这样,即使栈中局部变量(含final)已死亡,但由于它是final,其值永不变,因而局部内部类对象在变量死亡后,照样可以访问final型局部变量。(这一点我有些怀疑)
(5).归纳总结:局部内部类对象中包含有要访问的final型局部变量的一个拷贝,成为它的数据成员。因此,正是在这个意义上,final型局部变量的生命期,超过其方法的一次调用。严格来说,方法调用结束,所有的局部变量(含final)全死亡了。但:局部内部类对象中有final型局部变量的拷贝。

分享到:
评论

相关推荐

    Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释.doc

    Java中局部内部类可以访问它所在方法中定义的final修饰的局部变量的合理解释.doc

    【05-面向对象(下)】

    名字的局部变量,就使用该变量,如果不存在,则到该方法所在的内部类中查找是否存在该名字的属性,如果存在 则使用该属性。 •总之,第一步先找局部变量,第二步,内部类的属性,第三步。外部类的属性。 ...

    JAVA基础知识精华总结 收藏

    (4) 如果声明一个类为final,则所有的方法均为final,无论其是否被final修饰,但数据 成员可为final也可不是。 7、 接口interface (用implements来实现接口) (1) 接口中的所有数据均为 static和final即静态常量...

    java 面试题 总结

    如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的...

    超级有影响力霸气的Java面试题大全文档

    如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。子类的对象使用这个方法时,将调用子类中的定义,对它而言,父类中的定义如同被"屏蔽"了。如果在一个类中定义了多个同名的...

    day020-继承加强和设计模式代码和笔记.rar

    static是为了在静态方法中可以返回当前类中的对象 final:可加可不加,加了可以保证不可修改,且提供获取效率 3. 提供一个public修饰的方法getInstance给外部返回一个对象 4. 单例模式...

    二十三种设计模式【PDF版】

    设计模式之 Template(模板方法) 实际上向你介绍了为什么要使用 Java 抽象类,该模式原理简单,使用很普遍. 设计模式之 Strategy(策略) 不同算法各自封装,用户端可随意挑选需要的算法. 设计模式之 Chain of ...

    xheditor-1.1.14

    特别说明:两种初始化方法只能选择其中一种使用,如果两种方法的代码同时存在页面中,方法2的代码不会有任何效果。 我们更倾向于推荐大家使用方法1,因为更简单易用,不涉及任何的Javascript代码。通过简单的参数...

    sesvc.exe 阿萨德

    Entry 是 HashMap 中的一个内部类,从他的成员变量很容易看出: key 就是写入时的键。 value 自然就是值。 开始的时候就提到 HashMap 是由数组和链表组成,所以这个 next 就是用于实现链表结构。 hash 存放的是当前...

    中文简体压缩软件RAR 6.0

    在一个 UNIX 环境变量中,你需要将通配符置于引号中,避免被外壳扩展。例如, 这个命令将从当前路径中的 RAR 压缩文件解压所有的 *.asm 文件: rar e '*.rar' '*.asm' 命令可以是下列中的任何一个: ...

    WinRAR_4.0.exe

    在一个 UNIX 环境变量中,你需要将通配符置于引号中,避免被外壳扩展。例如, 这个命令将从当前路径中的 RAR 压缩文件解压所有的 *.asm 文件: rar e '*.rar' '*.asm' 命令可以是下列中的任何一个: a 添加...

    rar压缩软件.rar

    (存储在 HOME 环境变量中) Windows 的版本 RAR 从 rar.ini 文件读取配置文件信息,它放在 rar.exe 文件相 同的目录中。 这个文件包含下列字符串: switches=任何 RAR 开关,用空格分开 例如: switches=-...

    史上最全韩顺平传智播客PHP就业班视频,10月份全集

    8-17 1.apache服务器使用及配置④ apache虚拟主机 web访问时序图 8-17 2.apache服务器使用及配置⑤ 作业点评 提出apache和php整合的需求 8-17 3.php开发环境的搭建和使用① appserv套件安装 8-17 4.php开发环境的...

    史上最全传智播客PHP就业班视频课,8月份视频

    8-17 1.apache服务器使用及配置④ apache虚拟主机 web访问时序图 8-17 2.apache服务器使用及配置⑤ 作业点评 提出apache和php整合的需求 8-17 3.php开发环境的搭建和使用① appserv套件安装 8-17 4.php开发环境的...

    史上最全韩顺平传智播客PHP就业班视频,9月份全集

    8-17 1.apache服务器使用及配置④ apache虚拟主机 web访问时序图 8-17 2.apache服务器使用及配置⑤ 作业点评 提出apache和php整合的需求 8-17 3.php开发环境的搭建和使用① appserv套件安装 8-17 4.php开发环境的...

    (全)传智播客PHP就业班视频完整课程

    8-17 1.apache服务器使用及配置④ apache虚拟主机 web访问时序图 8-17 2.apache服务器使用及配置⑤ 作业点评 提出apache和php整合的需求 8-17 3.php开发环境的搭建和使用① appserv套件安装 8-17 4.php开发环境的...

    韩顺平PHP JS JQUERY 所有视频下载种子 货真价实

    8-17 1.apache服务器使用及配置④ apache虚拟主机 web访问时序图 8-17 2.apache服务器使用及配置⑤ 作业点评 提出apache和php整合的需求 8-17 3.php开发环境的搭建和使用① appserv套件安装 8-17 4.php开发环境的...

Global site tag (gtag.js) - Google Analytics