Java中的本地内部类
先决条件: Java中的嵌套类
本地内部类是在块内定义的内部类。通常,这个块是一个方法体。有时这个块可以是一个 for 循环或一个 if 子句。本地内部类不是任何封闭类的成员。它们属于定义它们的块,因此本地内部类不能有任何与之关联的访问修饰符。但是,它们可以标记为最终的或抽象的。这个类可以访问包含它的类的字段。本地内部类必须在定义它们的块中实例化。
本地内部类规则:
- 本地内部类的范围仅限于定义它们的块。
- 不能从创建它的块外部实例化本地内部类。
- 在 JDK 7 之前,Local 内部类只能访问封闭块的最终局部变量。但是,从 JDK 8 开始,可以在局部内部类中访问封闭块的非最终局部变量。
- 本地类可以访问其封闭类的成员。
- 本地内部类可以扩展抽象类或实现接口。
声明本地内部类:可以在块内声明本地内部类。此块可以是方法体、初始化块、for 循环,甚至是 if 语句。
访问成员:本地内部类可以访问包含它的类的字段以及定义它的块的字段。但是,这些类只有在声明为 final 或实际上是 final 时才能访问包含它的块的变量或参数。初始化后值不变的变量称为有效的最终变量。在方法体内定义的本地内部类可以访问其参数。
编译时会发生什么?
编译包含本地内部类的程序时,编译器会生成两个 .class 文件,一个用于外部类,另一个用于具有对外部类的引用的内部类。这两个文件由编译器命名为:
- 外部类
- 外部$1Inner.class
方法体内的声明
Java
// Java program to illustrate
// working of local inner classes
public class Outer
{
private void getValue()
{
// Note that local variable(sum) must be final till JDK 7
// hence this code will work only in JDK 8
int sum = 20;
// Local inner Class inside method
class Inner
{
public int divisor;
public int remainder;
public Inner()
{
divisor = 4;
remainder = sum%divisor;
}
private int getDivisor()
{
return divisor;
}
private int getRemainder()
{
return sum%divisor;
}
private int getQuotient()
{
System.out.println("Inside inner class");
return sum / divisor;
}
}
Inner inner = new Inner();
System.out.println("Divisor = "+ inner.getDivisor());
System.out.println("Remainder = " + inner.getRemainder());
System.out.println("Quotient = " + inner.getQuotient());
}
public static void main(String[] args)
{
Outer outer = new Outer();
outer.getValue();
}
}
Java
// Java program to illustrate Declaration of
// local inner classes inside an if statement
public class Outer
{
public int data = 10;
public int getData()
{
return data;
}
public static void main(String[] args)
{
Outer outer = new Outer();
if(outer.getData() < 20)
{
// Local inner class inside if clause
class Inner
{
public int getValue()
{
System.out.println("Inside Inner class");
return outer.data;
}
}
Inner inner = new Inner();
System.out.println(inner.getValue());
}
else
{
System.out.println("Inside Outer class");
}
}
}
Java
// Java code to demonstrate that inner
// classes cannot be declared as static
public class Outer
{
private int getValue(int data)
{
static class Inner
{
private int getData()
{
System.out.println("Inside inner class");
if(data < 10)
{
return 5;
}
else
{
return 15;
}
}
}
Inner inner = new Inner();
return inner.getData();
}
public static void main(String[] args)
{
Outer outer = new Outer();
System.out.println(outer.getValue(10));
}
}
Java
// Java code to demonstrate
// the scope of inner class
public class Outer
{
private void myMethod()
{
class Inner
{
private void innerMethod()
{
System.out.println("Inside inner class");
}
}
}
public static void main(String[] args)
{
Outer outer = new Outer();
Inner inner = new Inner();
System.out.println(inner.innerMethod());
}
}
Divisor = 4
Remainder = 0
Inside inner class
Quotient = 5
Note: A local class can access local variables and parameters of the enclosing block that are effectively final.
例如,如果在上例中的Inner类构造函数或Inner类的任何方法中添加突出显示的赋值语句:
public Inner()
{
sum = 50;
divisor = 4;
remainder = sum%divisor;
}
由于这个赋值语句,变量sum不再是有效的 final了。因此, Java编译器会生成类似于“从内部类引用的局部变量必须是最终的或有效的最终”的错误消息。
if 语句中的声明
Java
// Java program to illustrate Declaration of
// local inner classes inside an if statement
public class Outer
{
public int data = 10;
public int getData()
{
return data;
}
public static void main(String[] args)
{
Outer outer = new Outer();
if(outer.getData() < 20)
{
// Local inner class inside if clause
class Inner
{
public int getValue()
{
System.out.println("Inside Inner class");
return outer.data;
}
}
Inner inner = new Inner();
System.out.println(inner.getValue());
}
else
{
System.out.println("Inside Outer class");
}
}
}
Inside Inner class
10
演示内部类的错误代码
Java
// Java code to demonstrate that inner
// classes cannot be declared as static
public class Outer
{
private int getValue(int data)
{
static class Inner
{
private int getData()
{
System.out.println("Inside inner class");
if(data < 10)
{
return 5;
}
else
{
return 15;
}
}
}
Inner inner = new Inner();
return inner.getData();
}
public static void main(String[] args)
{
Outer outer = new Outer();
System.out.println(outer.getValue(10));
}
}
输出
Compilation error
说明:上述程序导致编译错误,因为内部类不能声明为静态。内部类与它们在其中定义的块相关联,而不是与外部类(在这种情况下为 Outer)相关联。
Java
// Java code to demonstrate
// the scope of inner class
public class Outer
{
private void myMethod()
{
class Inner
{
private void innerMethod()
{
System.out.println("Inside inner class");
}
}
}
public static void main(String[] args)
{
Outer outer = new Outer();
Inner inner = new Inner();
System.out.println(inner.innerMethod());
}
}
输出
prog.java:20: error: cannot find symbol
Inner inner = new Inner();
^
symbol: class Inner
location: class Outer
说明:上述程序导致编译错误,因为内部类的范围仅限于定义它们的块。