3

考虑以下:

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();
    }
  };

}

所以你可能会问自己我的问题是什么?这里是:

当将匿名类声明为接口常量时(请参阅我的上一个代码示例),匿名内部类对哪个外部类持有引用?

4

2 回答 2

4

接口中定义的字段总是隐式地具有修饰符public static final。它是一个常量,因此它没有关联的外部类。

此外,接口的成员类型是隐式的 public 和 static,这也适用于匿名类。

于 2012-11-09T10:34:46.800 回答
2

接口的内部类是隐式静态的,因此不需要引用外部类。

于 2012-11-09T10:46:33.600 回答