Java 方法内部类,内部类还可以定义在一个方法体中。我们看个例子,代码如下所示。
public class Outer {
private int a = 100;
public void test(final int param){
final String str = "hello";
class Inner {
public void innerMethod(){
System.out.println("outer a " +a);
System.out.println("param " +param);
System.out.println("local var " +str);
}
}
Inner inner = new Inner();
inner.innerMethod();
}
}
类Inner定义在外部类方法test中,方法内部类只能在定义的方法内被使用。如果方法是实例方法,则除了静态变量和方法,内部类还可以直接访问外部类的实例变量和方法,如innerMethod直接访问了外部私有实例变量a。如果方法是静态方法,则方法内部类只能访问外部类的静态变量和方法。方法内部类还可以直接访问方法的参数和方法中的局部变量,不过,这些变量必须被声明为final,如innerMethod直接访问了方法参数param和局部变量str。
方法内部类是怎么实现的呢?对于上述代码,系统生成的两个类代码大概如下所示。
public class Outer {
private int a = 100;
public void test(final int param) {
final String str = "hello";
OuterInner inner = new OuterInner(this, param);
inner.innerMethod();
}
static int access$0(Outer outer){
return outer.a;
}
}
public class OuterInner {
Outer outer;
int param;
OuterInner(Outer outer, int param){
this.outer = outer;
this.param = param;
}
public void innerMethod() {
System.out.println("outer a " + Outer.access$0(this.outer));
System.out.println("param " + param);
System.out.println("local var " + "hello");
}
}
与成员内部类类似,OuterInner类也有一个实例变量outer指向外部对象,在构造方法中被初始化,对外部私有实例变量的访问也是通过Outer添加的方法access$0
来进行的。
方法内部类可以访问方法中的参数和局部变量,这是通过在构造方法中传递参数来实现的,如OuterInner构造方法中有参数int param,在新建OuterInner对象时,Outer类将方法中的参数传递给了内部类,如OuterInner inner = new OuterInner(this, param);
。在上面的代码中,String str并没有被作为参数传递,这是因为它被定义为了常量,在生成的代码中,可以直接使用它的值。
这也解释了为什么方法内部类访问外部方法中的参数和局部变量时,这些变量必须被声明为final,因为实际上,方法内部类操作的并不是外部的变量,而是它自己的实例变量,只是这些变量的值和外部一样,对这些变量赋值,并不会改变外部的值,为避免混淆,所以干脆强制规定必须声明为final。
如果的确需要修改外部的变量,那么可以将变量改为只含该变量的数组,修改数组中的值,代码如下所示。
public class Outer {
public void test(){
final String[] str = new String[]{"hello"};
class Inner {
public void innerMethod(){
str[0] = "hello world";
}
}
Inner inner = new Inner();
inner.innerMethod();
System.out.println(str[0]);
}
}
str是一个只含一个元素的数组,方法内部类不能修改str本身,但可以修改它的数组元素。
通过前面介绍的语法和原理可以看出,方法内部类可以用成员内部类代替,至于方法参数,也可以作为参数传递给成员内部类。不过,如果类只在某个方法内被使用,使用方法内部类,可以实现更好的封装。
评论前必须登录!
注册