[code="java"]
public class Test1 {
interface Interface{int f1() ;}
Interface f(final int i){
return new Interface(){public int f1(){return i;}};
}
public static void main(String[] args){
Interface h=new Test1().f(6);
System.out.println(h.f1());
}
}
[/code]
按理来说,当f()被调用过之后i的生命周期随之结束,那匿名类如何保持下i的信息?
[quote]这也是我的猜测 [/quote]
你的内部类是一个接口类型,编译器虽产生了个Test1$Interface这样一个接口类型,但接口是不能实例化的,也即从class中找不到这个实例变量i指令;而对象的创建是在JVM实例中产生的,也即运行时才知道会有个h对象的产生,这个过程怎样把传递进来的i保存到h中,不清楚;
i 是个形参而已 ,哪儿来的什么生命周期啊
函数f(10)调用结束了 , 10的生命周期就结束了 ?
[quote]public static void main(String[] args){
Interface h=new Test1().f(6);
System.out.println(h.f1());
}
} [/quote]
h 对象的内部方法f1()的函数体为{return 6;} ,仅此而已 有什么问题?
实质上,跟下面这种形式是一样的道理
[code="java"]
class Type{
int i;
public Type(para){
this.i=para;
}
public f(){
return this.i;
}
}
System.out.println(new Type(i).f());
[/code]
你上面要想用匿名类保持下i的信息,做不到;
原因是匿名内部类是没有构造函数的,因为它没有类名,也即不能把参数给构造方法;传递的参数要想保存下来,需要将参数传递给它的超类型,而你提供的超类型是接口,接口也是不能有构造方法的,所以当f()被调用过之后,i的生命周期随之结束了。
改进一下,把Interface类型变成class,提供一个实例变量,定义一个含有一个整型参数的构造方法,这样匿名内部类的参数可以由其超类保存下来。
[quote]我这个h所引用的对象在i结束之后仍然存在,那
public int f1(){return i;}
中的i是怎么来的呢?[/quote]
确实,在[code="java"]Interface f(final int i){
return new Interface(){public int f1(){return i;}};
} [/code]这个方法中,i的生命周期在这个方法结束后,是不存在了的;但是内部类对象在这个方法结束后,却还存在,这样产生了局部变量的生命周期与内部类对象的生命周期的不一致性!而你运行这句[code="java"]System.out.println(h.f1()); [/code],显然i这个值还要存在这个h对象中,这样才能在[code="java"]new Test1().f(6);[/code]后,[code="java"]h.f1()[/code]还能访问i;对局部变量i进行了复制,为了做到复制的i在原来局部变量i的生命期结束后是同一个变量,用final来修饰局部变量i,这也是编译器强制要求这么做的,即匿名内部类要访问外部方法参数,方法参数必须是final的;
[quote]你上面要想用匿名类保持下i的信息,做不到;[/quote]应该是内部类保存了局部变量i的副本;