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

我们先稍微看一下代码:

从这里的提示可以看到,必须要将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能解

决之前我们提出的问题。









猜你喜欢

转载自blog.csdn.net/qq_41907991/article/details/80691485