我们先稍微看一下代码:

从这里的提示可以看到,必须要将a的修饰符变为final才行。

现在笔者就这一结果做出自己的分析:

首先来说,我们知道,方法被调用时会执行,当执行的时候,方法中的局部变量会加载到栈内存中,方法执

行完毕后局部变量会从栈中被释放(会被垃圾回收器立即回收)。其次,当一个对象被new出来后,new出来的

对象生存再堆(堆中的对象在用完后不会马上被回收),对象的引用存在于栈中,也会立即被收回。 结合以上的

代码我们可以发现,当test方法执行完成后,int类型的a变量立即被回收了,A对象的引用a1也被立即回收了,但

是new出来的A对象还是生存在堆上面,这个时候问题就出来了,一个活着对象持有一个被回收的变量。java作

为一种强类型语言,这种情况是肯定不允许的。

接下来我们分析,为什么加final后就可以了呢?

我们先看下面两段话:


final修饰局部变量

final修饰的局部变量一样需要被显式地赋初始值,因为Java本来就要求局部变量必须被显式地赋初始值。与普通变量不同的是,final修饰的局部变量被赋初始值之后,将不能再被重新赋值。

final修饰符的第一简单的功能就是一旦被赋初始值,将不可改变。
final的另一个简单的功能就是在定义了该final类变量时指定了初始值,且该初始值可以在编译时就被确定下来,系统将不会在静态初始化块中对该类变量赋初始值,而将是在类定义中直接使用该初始化值代替该final变量。

对于一个使用final修饰的变量而言,如果定义该final变量时就指定初始值,而且这个初始值可以在编译时就确定下来,那么这个final变量将不再是一个变量,系统会将其变成“宏变量”处理。所有出现该变量的地方,系统将直接把它当成对应的值处理。
执行“宏替换”的变量

final修饰符的一个重要用途就是定义“宏变量“,当定义final变量时就为该变量指定了初始值,而且该初始值可以在编译的时候就确定下来,那么这个final变量本质上就是一个”宏变量“,编译器会把程序中所用到该变量的地方直接替换成该变量的值。如果被赋的表达式只是基本的算术运算表达式或字符串连接运算,没有访问普通变量,调用方法,Java编译器同样会将这种final变量当成”宏变量“处理。

对于实例变量而言,可以在定义该变量时赋初始值之外,还可以在非静态初始化块、构造器中对它赋初始值,在这三个地方指定初始值的效果基本一样。但对于final实例变量而言,只有在定义该变量时指定初始值才会有”宏变量“的效果,在非静态初始化块、构造器中为final实例变量指定初始值则不会有这种效果。对于普通类变量而言,在定义时指定初始值,在静态初始化块中赋初始值的效果基本一样。但对于final类变量而言,只有在定义final类变量时指定初始值,系统才会对该final类变量执行”宏替换“

文字总是没有代码直观,接着我把上面代码的class文件反编译后得到如下代码:

先将未编译的java代码贴上来以做比较:

package com.itheima;
// 这是测试类
 public class Test { public void test(){ final int a = 10; A a1 = new A(){ public void show(){
System.out.println(a);
}
};
}
}
package com.itheima;
// 就一个show方法
public interface A { public void show();
}

反编译字节码文件后得到以下代码:

package com.itheima;

import java.io.PrintStream;

public class Test
{
public void test()
{
int a = 10; A a1 = new A()
{
public void show()
{
System.out.println(10); //在编译后,匿名内部类中的a直接被替换成了10
}
};
}
}

通过以上分析结合之前的两段问题,我认为,用final修饰后,匿名内部类中所引用的局部变量将以字面值常量的

形式存在,方法运行结束后,虽然方法中的局部变量被回收了,但是在匿名内部类并不受影响。所以加final能解

决之前我们提出的问题。

从垃圾回收机制解析为什么局部内部类只能访问final修饰的局部变量以及为什么加final能解决问题的更多相关文章

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

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

  2. Android(java)学习笔记150:为什么局部内部类只能访问外部类中的 final型的常量

    为什么匿名内部类参数必须为final类型: 1)  从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变 ...

  3. Android(java)学习笔记93:为什么局部内部类只能访问外部类中的 final型的常量

    为什么匿名内部类参数必须为final类型: 1)  从程序设计语言的理论上:局部内部类(即:定义在方法中的内部类),由于本身就是在方法内部(可出现在形式参数定义处或者方法体处),因而访问方法中的局部变 ...

  4. DAY20、垃圾回收机制,正则模块

    一.垃圾回收机制1.不能被程序访问到的数据,就称之为垃圾2.引用计数:每一次对值地址的引用都可以使该值得引用计数加1 每一次对值地址的释放都可以使该值得引用计数减一 当一个值的引用计数为0时,该值就会 ...

  5. java:面向对象(接口(续),Compareble重写,Comparator接口:比较器的重写,内部类,垃圾回收机制)

    接口: *接口定义:使用interface关键字 * [修饰符] interface 接口名 [extends 父接口1,父接口2...]{ * //常量的声明 * //方法的声明 * } *接口成员 ...

  6. 深入解析Java垃圾回收机制

    引入垃圾回收 哪些内存需要回收? 引用计数法 可达性分析 如何回收 Marking 标记 Normal Deletion 清除 Deletion with Compacting 压缩 为什么需要分代收 ...

  7. JavaScript 执行环境、作用域、内存管理及垃圾回收机制

    前言 JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存. [原理]找出那些不再继续使用的变量,然后释放其占用的内存.为此,垃圾收集器会按照固定的时间间隔( ...

  8. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

  9. JAVA的垃圾回收机制

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...

随机推荐

  1. 【Java】 Variable 变量

    什么是Variable变量? - 变量是内存中的一个存储区域 - 这个存储区域内的数据允许在同一类型范围内不断变化 - 是程序最基本的存储单元,包含三个要素[变量类型][变量名][存储的值] 为什么需 ...

  2. springboot 项目使用阿里云短信服务发送手机验证码

    1.注册阿里云账户进行账号实名认证 2.申请短信签名和模板 3.创建access_key和access_secret 4.然后就是代码编写 一.找到产品与服务里面的云通信模块,然后找到短信服务,开通短 ...

  3. CSS两种盒子模型:cntent-box和border-box

    cntent-box 平时普通盒子模型,padding,border盒子会变大,向外扩展border-box 特殊盒子模型,padding,border盒子会变大,向内扩展

  4. pytorch 手写数字识别项目 增量式训练

    dataset.py ''' 准备数据集 ''' import torch from torch.utils.data import DataLoader from torchvision.datas ...

  5. Ubuntu16.04 安装eclipse

    首先确保自己的Ubuntu已经安装了jdk并且配置好了环境变量 然后在官网下载相应的eclipse安装包: https://www.eclipse.org/downloads/packages/ 下载 ...

  6. spring-boot-lll-starter自动化框架介绍

    1. spring-boot-lll-starter自动化框架介绍 1.1. 前言 舔着脸来介绍一波我刚写的自动化框架,spring-boot-lll-starter框架是经由我企业实战总结的一套,适 ...

  7. Apk优化极致

    1. webp WebP格式,谷歌(google)开发的一种旨在加快图片加载速度的图片格式.图片压缩体积大约只有JPEG的2/3,并能节省大量的服务器宽带资源和数据空间.Facebook Ebay等知 ...

  8. web.config 301

    <?xml version="1.0" encoding="UTF-8"?> <configuration> <system.we ...

  9. [Inno Setup] 如何读取命令行输入的参数

    以 /verysilent 为例 [Code] var isVerySilent: Boolean; function InitializeSetup(): Boolean; var j: Integ ...

  10. Linux 如何通过 iscsi target name 获取 ip

    by Mike Andrews # lsscsi -t [:::] disk iqn.-.com.blockbridge:t-pjxfzufjkp-illoghjk,t,0x1 /dev/sda [: ...