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

Posted

技术标签:

【中文标题】在接口中声明的匿名内部类:啥是外部类?【英文标题】:Anonymous innerclass declared in an interface: what is the outerclass?在接口中声明的匿名内部类:什么是外部类? 【发布时间】:2012-11-09 10:29:30 【问题描述】:

考虑以下几点:

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

常规的 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();
    
  ;



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

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

【问题讨论】:

刚试了一下,函数实例中根本没有属性 【参考方案1】:

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

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

【讨论】:

那么,隐含的static 是这里的关键吗? 那个,以及接口本身隐含的static。接口、枚举和注解总是static 这是我解释的。但是对该函数的引用是静态的这一事实并不能解释为什么它不像另一个匿名内部类。确实可以对引用外部类的任意声明的类进行静态引用。 @SebastienLorber 看到 Alexei 的回答【参考方案2】:

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

【讨论】:

所以你的意思是匿名内部类,在这种特殊情况下,就像一个“匿名静态内部类”?我理解这个概念,但你有任何解释它的链接吗? @SebastienLorber docs.oracle.com/javase/specs/jls/se7/html/jls-9.html#jls-9.5

以上是关于在接口中声明的匿名内部类:啥是外部类?的主要内容,如果未能解决你的问题,请参考以下文章

JAVA学习之局部内部类,匿名内部类,静态内部类

java 匿名内部类

匿名内部类不能访问外部类方法中的局部变量,除非变量被声明为final类型

Java面向对象 —— 抽象类接口内部类匿名内部类

java基础之匿名内部类

java中关于内部类和匿名内部类