Java内部类分为4个部分进行阐述,分别为概览、成员内部类、局部内部类和匿名内部类。


在本文中是Java内部类的局部内部类,主要讲局部内部类的概念和在使用局部内部的过程中,需要注意的一个细节。



1、局部内部类的概念


   在一个类的方法内部定义另外一个类,那么另外一个类就称作为局部内部类。



class OutterClass
{	
	void test()
	{	
		class InnerClass//局部内部类
		{
		}
	}
}

在上述代码中,InnerClass定义在OutterClass的test方法的内部,因此InnerClass是局部内部类。



2、局部内部类要注意的一个细节

   如果局部内部类访问了一个局部变量,那么该局部变量必须使用final修饰


示例代码:

package com.rk.innerclass;

class OutterClass
{	
	void test()
	{
		int i = 100;
		final int x = i;//局部变量
		
		class InnerClass//局部内部类
		{
			void print()
			{
				System.out.println("test方法中x的值为:" + x);
			}
		}
		
		InnerClass inner = new InnerClass();
		inner.print();
		
		System.out.println("i=" + i + ",x=" + x);
	}
}

public class InnerClassLearn
{
	public static void main(String[] args)
	{
		OutterClass outter = new OutterClass();
		outter.test();
	}
}

在上述代码中,OutterClass类的test方法中定义了一个x变量(final int x = 100;),由于在局部内部类InnerClass中需要访问x变量,x变量需要用final修饰。


进一步解释一下,为什么x需要被final进行修饰:

(1)x变量什么时候从内存中消失? test方法执行完毕之后x就会消失。

(2)当test方法执行完毕之后,那么x马上从内存中消失,而InnerClass对象在方法执行完毕的时候还没有从内存中消失,而InnerClass对象的print方法还在访问着x变量,这时候的x变量已经消失了,那么就给人感觉x的生命变量已经被延长了。


换一种更好理解的方式来说,如果OutterClass类的test的方法需要执行5秒钟,而InnerClass类的print方法需要执行10秒钟。在经过5秒之后,①OutterClass类的test方法就要执行完毕了,局部变量x也会从栈内存上消失,而②InnerClass类的print方法还在继续执行中,还需要访问变量x,那么①和②之间就产生了冲突。


解决方案: 如果一个“局部内部类”访问一个“局部变量”的时候,那么就让“该局部内部类”访问“这个局部变量”的复制品。

用myeclipse的1.4版本的Java Compiler进行编译,再用jd.exe(Java Decompiler)进行反编译,得到如下代码:

class OutterClass
{
  class 1$InnerClass//这里将“局部内部类”变成了“成员内部类”
  {
    private final int val$x;//这里定义了一个final修饰的val$x变量
    
    1$InnerClass(int paramInt)//创建了一个带参数的构造方法
    {
      this.val$x = paramInt;
    }
    
    void print()
    {
      System.out.println("test方法中x的值为:" + this.val$x);//这里使用的是自身的val$x变量
    }
  }
  
  void test()
  {
    int i = 100;
    int x = i;

    1.InnerClass inner = new 1.InnerClass(x);//这里调用1.InnerClass类的构造函数
    inner.print();
    
    System.out.println("i=" + i + ",x=" + x);
  }
}

用myeclipse的1.5版本的Java Compiler进行编译,再用jd.exe(Java Decompiler)进行反编译,得到如下代码:

class OutterClass
{
  void test()
  {
    int i = 100;
    final int x = i;
    
    Object inner = new Object()//这里用到了匿名内部类
    {
      void print()
      {
        System.out.println("test方法中x的值为:" + x);
      }
    };
    inner.print();
    
    System.out.println("i=" + i + ",x=" + x);
  }
}



3、思维导图

wKiom1cPpZrDAjsfAAC1lMLBRUI053.png