在接口中声明的匿名内部类:什么是外部类?

时间:2012-11-09 10:29:31

标签: java scjp ocpjp open-closed-principle

请考虑以下事项:

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访问(在这种情况下特别有用,其中有一个“命名” colision“


创建匿名内部类时,它是相同的:创建的匿名内部类包含对外部类的引用,这就是为什么在方法内部声明谓词(匿名方法 - 本地内部类)时,我们仍然可以访问innerclass,外部类的变量,而不必将它们声明为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时,我通常在我的接口函数和谓词中声明,这允许我利用像Maps.uniqueIndex(...)这样有用的Guava函数。

public interface AlternativeNameable {

  String getAlternativeName();

  Function<AlternativeNameable,String> GET_ALTERNATIVE_NAME = new Function<AlternativeNameable,String>() {
    @Override
    public String apply(AlternativeNameable input) {
      return input.getAlternativeName();
    }
  };

}

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

当声明一个匿名类作为接口常量时(参见我的上一个代码示例),匿名内部类在哪个外部类上保存对引用的引用?

2 个答案:

答案 0 :(得分:4)

接口always implicitly have the modifiers public static final中定义的字段。它是一个常数,因此它没有相关的外部类。

此外,member types of interfaces are implicitly public and static也适用于匿名类。

答案 1 :(得分:2)

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