内部类访问局部变量的时候,为什么变量必须加上final修饰

这里的局部变量就是在类方法中的变量,能访问方法中变量的类当然也是局部内部类了。
我们都知道,局部变量在所处的函数执行完之后就释放了,但是内部类对象如果还有引用指向的话它是还存在的。例如下面的代码:

class Outer{                                                                       public static void main(String[] args){ Outer out = new Outer(); Object obj = out.method(); } Object method(){ int locvar = 1; class Inner{ void displayLocvar(){ System.out.println("locvar = " + locvar); } } Object in = new Inner(); return in; } } 

当out.method()方法执行结束后,局部变量 locvar 就消失了,但是在method()方法中 obj in = new Inner() 产生的 in 对象还存在引用obj,这样对象就访问了一个不存在的变量,是不允许的。这种矛盾是由局部内部类可以访问局部变量但是局部内部类对象和局部变量的生命周期不同而引起的。

局部内部类访问局部变量的机制

在java中,类是封装的,内部类也不例外。我们知道,非静态内部类能够访问外部类成员是因为它持有外部类对象的引用 Outer.this, 就像子类对像能够访问父类成员是持有父类对象引用super一样。局部内部类也和一般内部类一样,只持有了Outer.this,能够访问外部类成员,但是它又是如何访问到局部变量的呢?

实际上java是将局部变量作为参数传给了局部内部类的构造函数,而将其作为内部类的成员属性封装在了类中。我们看到的内部类访问局部变量实际上只是访问了自己的成员属性而已,这和类的封装性是一致的。那么上面的代码实际上是这样:

Object method(){int locvar = 1; class Inner{ private int obj; public Inner(int obj){ this.obj = obj; } void displayLocvar(){ System.out.println("locvar = " + locvar); } } Object in = new Inner(locvar); //将locvar作为参数传给构造,以初始话成员 return in; } 

那么问题又来了,我们写代码的目的是在内部类中直接控制局部变量和引用,但是java这么整我们就不高兴了,我在内部类中整半天想着是在操作外部变量,结果你给整个副本给我,我搞半天丫是整我自己的东西啊?要是java不这么整吧,由破坏了封装性--------你个局部内部类牛啊,啥都没有还能看局部变量呢。这不是java风格,肯定不能这么干。这咋整呢?
想想,类的封装性咱们一定是要遵守的,不能破坏大局啊。但又要保证两个东西是一模一样的,包括对象和普通变量,那就使用final嘛,当传递普通变量的之前我把它变成一个常量给你,当传递引用对象的时候加上final就声明了这个引用就只能指着这一个对象了。这样就保证了内外统一。

 

 

转:https://segmentfault.com/a/1190000002735907

转载于:https://www.cnblogs.com/xh0102/p/5729381.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/418214.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

创建接口匿名实现类的对象的四种方法

package InterfactTest; public class InterfaceTest { public static void main(String[] args) { // TODO Auto-generated method stub Computer com new Computer(); com.transferData(new Print()); //创建了非匿名实现类的匿名对象 …

Thinkphp 数据库配置参数

mysql配置 DB_USER > array(DB_TYPE > mysql,DB_HOST > 127.0.0.1,DB_NAME > blog,DB_USER > root,DB_PWD > ,DB_PORT > 3306,DB_PREFIX > ,DB_CHARSET> utf8, // 字符集), Oracle配置(模式) DB_DATA > array(DB_TYPE >…

代理模式简单模板

package ProxyTest;//接口的应用:代理模式public class NetWorkTest {public static void main(String[] args) {Server se new Server();new ProxyServer(se).browse();} }interface NetWork{void browse(); }//被代理类 class Server implements NetWork{Overridepublic voi…

写出gradle风格的groovy代码

写出gradle风格的groovy代码 我们先来看一段gradle中的代码: buildscript {repositories {jcenter()}dependencies {classpath com.android.tools.build:gradle:2.1.2} }allprojects {repositories {jcenter()} }task clean(type: Delete) {delete rootProject.buil…

这个社会根本不存在值得我们去仰视的人和事

想改变世界,从整理床铺开始。如果你每天早上整理床铺,你就完成了一天中的第一个任务,这会给你小小的自豪感,并激励你去完成另一个任务,一个接一个的任务。一天下来,每个已经完成的小任务会积累成很多大任务…

ipv6问题

1)百度搜索:针对苹果最新审核要求为应用兼容IPv6 2) ipV6测试网址:http://test-ipv6.com/ http://ipv6.jmu.edu.cn/ http://ipv6test.google.com/   你可以在浏览器输入这些地址,测试你是否已经使用了ipv6地址。 3&a…

JAVA8后接口的新特性

知识点一: 知识点二: 知识点三: 知识点四: 知识点五:

抽象类和接口的共同点和区别

抽象类和接口个共同点和区别: 共同点: 不能实例化,都可以被继承 不同点: 抽象类有构造器,单继承性 接口没有构造器,多继承性

mybatis里oracle与MySQL的insert_update

需求&#xff1a;gisdata表中插入数据&#xff0c;如果wxid数据存在就更新&#xff0c;不存在就插入 Mysql的mybatis配置 1 <?xml version"1.0" encoding"UTF-8"?>2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 3…

input的type属性的修改

记录一下成长的历程吧&#xff01; 刚开始写&#xff0c;没什么文笔&#xff0c;也没什么技术含量&#xff0c;可能主要的是纪录一下平常工作学习中遇到的问题&#xff0c;以及解决的办法吧。或者只有问题&#xff0c;没有解决办法。 前两天项目中遇到的一个问题&#xff0c;由…

程序 进程 线程

并行&#xff1a;再球场上&#xff0c;每个人都有篮球&#xff0c;都自己玩自己的 并发&#xff1a;只有一个球&#xff0c;一堆人玩 球&#xff08;CPU&#xff09; 人&#xff08;线程&#xff09; t1这个线程对象&#xff0c;是再主线程造的&#xff0c;以及执行t1.start…