Anonymous Inner 类 实际上不是子类吗?

Aren't Anonymous Inner Classes actually subclasses?

假设 A 是自定义的 class,并考虑以下匿名内部 class 的声明:

A Obj = new A() {
    @Override
    public String toString() {
        return "Hello!";
    }
}

在这种情况下,Obj 是匿名内部 class 的实例,其 toString 方法已被覆盖。由于它是用类型 A 声明的,所以匿名 class 必须是 A 的子 class。那么,为什么这个 class 不称为匿名子 class 而不是匿名内部 class? 'inner' 从哪里来?

是的,objA 的子 class 的实例。您可以通过调用 obj.getClass().getSuperclass():

来验证 superclass

打印出如下内容:

class Whosebug.Test //obj.getClass()
class Whosebug.A //obj.getClass().getSuperclass()

So then, why isn't this class called an Anonymous Subclass instead of an anonymous inner class?

那些只是语义。这是一个名字。然而,可能有很多原因,其中之一是匿名 classes 可以直接实现接口:

Runnable r = new Runnable() {
    public void run() {}
}

这不是任何对象的子class(但是对象,但不是对象的子class...),但它也是匿名的class .

子class和内class是匿名class的两个不同方面。由于语法原因,匿名 class 显然是命名 class 的子 class,因此 inner 方面与分类更相关.

Java class是这样的分类1:

如您所见,匿名 class 是内部嵌套 class。

分类未指定 class 是子 class、基础 class 还是独立 class。任何类别的 类 都可以是子 class 或基础 class。由于 ,匿名 class 可以从接口定义,在这种情况下它根本不是子 class。

1) .

末尾更大层次结构的摘录

Why isn't this class called an Anonymous Subclass instead of an anonymous inner class?

  • 因为(通常)匿名内部 class 不一定是 subclasses1。匿名内部 class 可以扩展接口而不是 class.

  • 因为"subclass-ness"在大多数我们谈论匿名内部的上下文中2不重要classes.

  • 因为人是懒惰的3而"Anonymous Inner Subclasses"多了一个音节。或者换句话说,人们有一种自然倾向优化他们的演讲和写作模式。

  • 因为...惯例。

Where does the 'inner' come from?

Inner 在 Java 中具有技术意义。这意味着两件事。

  • 表示class是在另一个class中声明的。
  • 表示允许class引用封闭class.
  • 实例的this

请参阅@Andreas 的回答中的分类法。


历史脚注。

其实官方术语是AnonymousClass。事实上,Sun 在 Java 1.1 中使用术语 "Anonymous Class" 而不是 "Anonymous Inner Class",当时该结构被添加到语言中。例如,Java 1.1.4 发行说明中的​​ "Inner Class Specification" 在大多数情况下将它们称为 "Anonymous Classes" ...。

我怀疑发生的事情是 Sun 早期的演示文稿或论文中存在一些不一致,并且许多非 Sun 作者在他们的作品中锁定了 "anonymous inner class" 版本。 Sun 团队试图通过使用官方 Java 语言规范和教程中的 "Anonymous Class" 悄悄纠正这个问题。但为时已晚了。书在书店,文章在网上。


1 - 除了微不足道的意义。每个不是 Object 的 class 必须是 some class.

的子class

2 - 同样,您通常会说 "I am taking the dog for a walk",而不是 "I am taking the black Labrador for a walk"。

3 - 在这种情况下,"good lazy".

回答你的问题标题,是的,他们是。匿名内部 classes 实际上是 subclasses.

"Since it was declared with type A, the anonymous class, [Obj], must be a subclass of A."

干得好。 :)

无论如何,回答为什么 "inner" 在那里:如果你在另一个 class 中声明一个匿名 class (并且匿名 class 不是静态声明的,下面有更多内容)然后它将能够像内部 class 一样访问其周围的 class 。例如:

public class Outer {
    private final int someRandomValue = 4;

    public final Object anonymousInnerInstance = new Object() {
        @Override
        public String toString() {
            // Notice how this class has access to a field declared inside a different
            // class. More specifically, this anonymous class can access someRandomValue,
            // even though someRandomValue belongs to the class, Outer.
            return "Anonymous Inner Class: " + someRandomValue;
        }
    };

    public class RegularInner {
        @Override
        public String toString() {
            // This regular inner class is inside Outer, (just like the anonymous class),
            // and can access any of Outer's fields (amongst Outer's other things).
            return "Regular Inner Class: " + someRandomValue;
        }
    }

    public final RegularInner regularInnerInstance = new RegularInner();

    public static void main(String[] args) {
        Outer outerInstance = new Outer();
        System.out.println(outerInstance.anonymousInnerInstance);
        System.out.println(outerInstance.regularInnerInstance);

        // By the way, you can make new RegularInner instances off of our Outer
        // instance:
        RegularInner newInnerInstance = outerInstance.new RegularInner();
        // When you write "outerInstance.new SomeClass()" you're saying:
        // "I'd like to initialize my 'SomeClass' object with 'outerInstance',
        // as its container." This effectively means that any variables that
        // belong to Outer that your SomeClass needs to access, it will access
        // from the Outer instance you gave it.
    }
}

因此,anonymousInnerInstance 的底层 class 和 class RegularInner 都可以访问 Outer 的字段,而其他 instance-specific 属于 Outer 的内容。这就是为什么匿名 class 有时可能被称为 "inner" class.

任何内部 class 的实例都需要使用外部 class 的实例来创建以备份它,否则它将不知道哪个 object,(不是class),属于.


静态垃圾

如果匿名 class 被声明为 static,它将无法访问其周围 class 的内容并且不会是 "inner" class(相反,它将是一个匿名 "nested" class)。

public class Outer {
    private final int someRandomValue = 4;

    public static final Object anonymousStaticInstance = new Object() {
        @Override
        public String toString() {
            // someRandomValue belongs to an INSTANCE of Outer. (So each Outer object you
            // have has its own someRandomValue). Since this anonymous class
            // is now static, it is no longer tied to an instance of Outer. It doesn't have
            // an Outer object that it can read "someRandomValue" from. The same goes for
            // RegularStatic, below.
            return "Anonymous Inner Class: " + someRandomValue;
        }
    };

    public static class RegularStatic {
        @Override
        public String toString() {
            return "Regular Inner Class: " + someRandomValue;
        }
    }

    public final RegularStatic regularInnerInstance = new RegularStatic();

    public static void main(String[] args) {
        Outer outerInstance = new Outer();
        System.out.println(outerInstance.anonymousStaticInstance);// Java warns you here and
        // tells you to access anonymousStaticInstance statically. This is because
        // anonymousStaticInstance no longer belongs to any given instance of Outer.
        // There is only one anonymousStaticInstance, that "belongs" to the class Outer,
        // rather than multiple anonymousInnerInstances which each belong to an instance
        // of Outer.
        System.out.println(outerInstance.regularInnerInstance);
    }
}

请记住,匿名 class 可以是 "inner" "nested"。因此,在笼统地谈论它们时,只需说 "anonymous class"。 (匿名内部classes是一种匿名class)。另外,请务必阅读评论,因为他们给出了大部分解释。

有什么问题吗? :)