考虑以下:
public class OuterClass {
private String attribute = "outer";
class InnerClass {
private String attribute = "inner";
public doSomething() {
System.out.println(this.attribute);
System.out.println(OuterClass.this.attribute);
}
}
}
InnerClass 不是静态的,必须针对其外部类的实例创建。
new OuterClass().new InnerClass()
常规的内部类包含对创建它的外部类的引用,可以使用Outer.this.myAttribute
(在存在“命名冲突”的情况下特别有用
创建匿名内部类时也是一样:创建的匿名内部类持有对外部类的引用,这就是为什么在方法内部声明谓词(匿名方法局部内部类)时,我们仍然可以在内部类内部访问外部类的变量,而不必将它们声明为 final(而我们应该将变量作为方法参数传递。
public class OuterClass {
// Do not need to be final because the innerclass keeps a reference to the outerclass
// even if it's an anonymous innerclass, it's still an innerclass
private String classAttribute = "classAttribute";
public Runnable doSomething() {
// Should be final because the variable lives on the stack and the reference to this object
// must be copied so that the String object is still accessible when the stack frame is destroyed
final String localVar = "localVar";
return new Runnable() {
@Override
public void run() {
System.out.println(classAttribute);
System.out.println(localVar);
}
};
}
}
最后,我们可以在接口中声明常量,这些常量被隐式标记为 public static final。一个对象可以是一个常数。因此,作为匿名内部类创建的对象是接口的合法常量。
例如,在使用 Guava 时,我通常在我的接口函数和谓词中声明,这允许我利用有用的 Guava 函数,例如Maps.uniqueIndex(...)
.
public interface AlternativeNameable {
String getAlternativeName();
Function<AlternativeNameable,String> GET_ALTERNATIVE_NAME = new Function<AlternativeNameable,String>() {
@Override
public String apply(AlternativeNameable input) {
return input.getAlternativeName();
}
};
}
所以你可能会问自己我的问题是什么?这里是:
当将匿名类声明为接口常量时(请参阅我的上一个代码示例),匿名内部类对哪个外部类持有引用?