黑马程序员技术交流社区

标题: 问大神们一个有关final的问题 [打印本页]

作者: leojr    时间: 2016-11-29 21:21
标题: 问大神们一个有关final的问题
局部内部类如果要想使用局部变量就必须在变量前面加final,为啥final修饰后的变量生命周期延长了,望大神给详细的分析一下!还有局部内部类创建的对象的生命周期为啥可能比方法的生命要长呢

作者: 飞扬跋扈    时间: 2016-11-29 22:35
加final,局部变量就成为了常量。常量的生命周期非常长。
第二个问题:常量就是不会改变的量,肯定比对象长

作者: 1413157322    时间: 2016-11-29 22:42
一、
首先用final修饰的变量称为常量,存储在方法区的常量池中,随着类的加载而加载,类的消失而消失;
而没被final修饰的局部变量随着方法的加载而加载,方法的弹栈而消失;
二、
第二个问题涉及到java的垃圾回收机制,当方法弹栈时内部对象没有被引用后成为垃圾,但此时并没有及时被清除,
只有当堆内存区的占用到达一定限度(不够用)时,该对象才会真正地自动被清除。
作者: leojr    时间: 2016-11-29 22:47
1413157322 发表于 2016-11-29 22:42
一、
首先用final修饰的变量称为常量,存储在方法区的常量池中,随着类的加载而加载,类的消失而消失;
而 ...

谢谢大神,受教了我对这些底层的东西还是了解不够深入

作者: lieyemu    时间: 2016-11-29 23:07
6666666666
作者: 201314    时间: 2016-11-29 23:11
好好学习,天天向上。
作者: xyy222    时间: 2016-11-29 23:47
对于方法内部类(匿名内部类)来说,因为内部类要访问所在方法中的局部变量,这时候用持有的外部类当前对象引用还能调用的到吗?
调不到了,那Java语言的设计者是这么来解决这个问题的:将局部变量复制一份给内部类使用,怎么复制的?在内部类初始化的时候通过构造方法传值的方式。
这样,内部类中会有一份复制的private修饰的成员变量。这样我就能访问了。但问题又来了,比如:
[java] view plain copy print?
public void fun() {  
    int i = 1;  
    class Inner{  
        // int i = 1; 由编译器生成  
        public void print() { i++ }  
    }  
    System.out.println("i=" + i);   
    // 还是会输出i=1,我们明明在内部类方法中对此变量进行++了啊。抱歉,您++的是被复制的另一份。  
}

问题的引出<保持两个不同变量的一致性>:

好,问题就这么无情的出现了,怎么解决?Java又说了,要不然给局部变量加上final吧,这样就会保持值得一致性了。
ok,问题解决,这就是为什么方法内部类访问的局部变量必须被final修饰的终极原因(为了约束两个不同变量的一致性)。设计问题,挺无奈的解决方案。


来看看另一种说法:
在Java中,方法的局部变量位于栈上,对象位于堆上。
因为局部变量的范围被限制在该方法内,当一个方法结束时,栈结构被删除,该变量消失。
但是,定义在这个类中的内部类对象仍然存活在堆上,所以内部类对象不能使用局部变量。除非这些局部变量被标识为最终的。


这种说法是片面的,因为根本原因是内部类对象无法访问局部变量,才会去复制一份。
为了保证两个变量的一致性,才去使用final关键字修饰局部变量。而不是因为栈生命周期与堆生命周期不一致的问题。
作者: chenyanwei6    时间: 2016-11-30 00:21
解释的好详细啊
作者: leojr    时间: 2016-11-30 07:27
xyy222 发表于 2016-11-29 23:47
对于方法内部类(匿名内部类)来说,因为内部类要访问所在方法中的局部变量,这时候用持有的外部类当前对象 ...

大牛,好详细

作者: cheukfan    时间: 2016-11-30 07:42
因为变成了常量




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2