这是java的一条规则。那么为什么会有这条规则呢?要想弄懂这个问题,就需要弄懂局部内部类对象和局部变量的生命周期谁更长的问题。

首先,看一段代码,以没有将变量声明为final的代码作为例子,代码如下:

 class Outer{

     Object obj;
public void outerMethod() { //局部变量
int x = 5;
//定义在方法中的内部类称为局部内部类
class Inner{ public String toString() {
System.out.println(x);//访问了局部变量x
          return null; 
}
}
//创建内部类实例
Inner in = new Inner();
in.toString();
//将内部类实例的引用赋值给obj
obj = in;
}
}
public class HelloDemo { public static void main(String[] argr) {
Outer out = new Outer();
out.outerMethod();
  
   }
}

  如上面的第7行代码所示,变量x没有被声明为final,如果是这样的话,当执行完第26行的outMethod()方法后,outMethod()方法将出栈,出栈后outMethod()方法里面定义的所有变量(x 和 in)都死亡了,(但是此时内部类的对象还活着,直到它不再被使用才会被回收,也就是说此内部类对象的生命周期比局部变量的生命周期长),并且在变量 in 死亡之前,in 的值赋值给了成员变量obj(第19行代码),这时obj 指向了内部类的对象,如果此时在27行执行一条代码: out.obj.toString();那么这条代码将会访问到局部变量 x,但是此时 x 已经死亡了,内部类对象已经访问不到 x 了,因此这是相互矛盾的。所以上面的代码实际上并不能编译通过。(在jdk8.0能编译通过,那是因为它检测到局部内部类访问了 x,会默认给 x 的前面加上隐式的final,如果在第8行加上一句代码:x = 4;编译器将会报错,因为final不允许 x 的值改变)

  如果局部变量 x 被声明为final后(在第七行的int前加上final),x 就代表了一个常量,那么第15行的代码实际上就变成了 System.out.println(5);,这时内部类相当于访问了一个数字5。这是没任何问题的,因此局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final。究其根本原因,是局部内部类对象的生命周期比局部变量的生命周期长。

2018-05-11  22:10:16

局部内部类访问它所在方法的局部变量时,要求该局部变量必须声明为final的原因的更多相关文章

  1. java-内部类访问特点-私有成员内部类-静态成员内部类-局部内部类访问局部变量

    1.内部类访问特点: - 内部类可以直接访问外部类的成员,包括私有. - 外部类要访问内部类的成员,必须创建对象. - 外部类名.内部类名 对象名 = 外部类对象.内部类对象: - 例: class ...

  2. 匿名/局部内部类访问局部变量时,为什么局部变量必须加final

    我们都知道方法中的匿名/局部内部类是能够访问同一个方法中的局部变量的,但是为什么局部变量要加上一个final呢? 首先我们来研究一下变量生命周期的问题,局部变量的生命周期是当该方法被调用时在栈中被创建 ...

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

    大部分时候,类被定义成一个独立的程序单元.在某些情况下,也会把一个类放在另一个类的内部定义,这个定义在其他类内部的类就被称为内部类,包含内部类的类也被称为外部类. class Outer { priv ...

  4. 为什么局部内部类访问外边的局部变量必须为final

    6.局部内部类访问外边的局部变量时,此变量必须为final类型 马克-to-win:由于技术方面的限制,java的设计者们做出如下语法规定:局部内部类访问外边的局部变量时,此变量必须为final类型, ...

  5. “全栈2019”Java第九十八章:局部内部类访问作用域成员详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  6. 局部内部类访问方法中的局部变量为什么加final

    转载:http://www.cnblogs.com/mjblogs/p/4971630.html 1)从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形 ...

  7. 局部内部类访问方法的参数和局部变量必须是final的

    内部类的种类一共分为四种,我看其他几种内部类的时候思路都是很清晰的,然后我就碰到了这一条:"方法中的内部类可以访问外部类成员.对于方法的参数和局部变量,必须有final修饰才可以访问&quo ...

  8. 使用JavaScript访问子节点方法elementNode.childNodes时,需要注意的地方

    有这样一个HTML结构 <div> javascript <p>javascript</p> <div>jQuery</div> <h ...

  9. Java学习笔记23---内部类之局部内部类只能访问final的局部变量

    局部内部类是定义在方法体或代码块中的类,在笔记19中已有过简单介绍. 今天要讨论的是局部内部类为什么只能访问为常量的局部变量. 作者: 博客园--蝉蝉 请尊重作者劳动成果,转载请在标题注明“转载”字样 ...

随机推荐

  1. (NO.00001)iOS游戏SpeedBoy Lite成形记(十五)

    现在啃第2个问题:如何让玩家输入赌注金额. 实现的方法有很多种,比如可以限制玩家只能从特定的金额中选择,把每个选择做成一个按钮即可.以下是一个假想选择窗口的示意图: 这样没有玩家的输入问题了.缺点是不 ...

  2. 程序员的视角:java GC

    GC(Garbage Collection 垃圾回收)的概念随着 java 的流行而被人们所熟知. 实际 GC 最早起源于20世纪60年代的 LISP 语言,是一种自动的内存管理机制. GC 要解决的 ...

  3. AngularJS进阶(二十四)AngularJS与单选框及多选框的双向动态绑定

    AngularJS与单选框及多选框的双向动态绑定      赠人玫瑰,手留余香.若您感觉此篇博文对您有用,请花费2秒时间点个赞,您的鼓励是我不断前进的动力,共勉! AngularJS 在 <in ...

  4. HDFS读写数据过程

    一.文件的打开 1.1.客户端 HDFS打开一个文件,需要在客户端调用DistributedFileSystem.open(Path f, int bufferSize),其实现为: public F ...

  5. Android服务器——TomCat服务器的搭建

    Android服务器--TomCat服务器的搭建 作为一个开发人员,当然是需要自己调试一些程序的,这个时候本地的服务器就十分方便了,一般都会使用TomCat或者IIS服务器,IIS就比较简单了,其实t ...

  6. 使用代码刷QQ的跨年红包

    使用的库从这里找: https://github.com/GameTerminator/dont-touch-white 关键代码就是一个while循环加上drag. import com.andro ...

  7. Ubuntu安装java的最简单的命令行方式

    由于经常要安装java,因此 深受其烦! 分为两部: 1. sudo apt-get install openjdk-7-jdk 2. sudo vim /etc/environment 然后把下面的 ...

  8. unix下各种查看“变量”的命令比较

    子程序只会继承父程序的环境变量,而不继承其自定义变量. env 查看所有环境变量 set 查看所有变量,包括环境变量和自定义变量 set 还可以给程序位置参数赋值: set 1 2 3 将1赋值给$1 ...

  9. jQuery插件之----缓冲运动

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. 排序算法入门之快速排序(java实现)

    快速排序也是一种分治的排序算法.快速排序和归并排序是互补的:归并排序将数组分成两个子数组分别排序,并将有序的子数组归并以将整个数组排序,会需要一个额外的数组:而快速排序的排序方式是当两个子数组都有序时 ...