[英]Aren't Anonymous Inner Classes actually subclasses?
假设 A 是一个自定义类,并考虑以下匿名内部类的声明:
A Obj = new A() {
@Override
public String toString() {
return "Hello!";
}
}
在这种情况下,Obj 是一个匿名内部类的实例,其 toString 方法已被覆盖。 既然是用类型A声明的,那么匿名类一定是A的子类。那么,为什么这个类不称为匿名子类而不是匿名内部类呢? “内在”从何而来?
是的, obj
是A
的子类的实例。 您可以通过调用obj.getClass().getSuperclass()
来验证超类:
这会打印如下内容:
class stackoverflow.Test$1 //obj.getClass()
class stackoverflow.A //obj.getClass().getSuperclass()
那么,为什么这个类不称为匿名子类而不是匿名内部类呢?
这些只是语义。 这是一个名字。 然而,可能有很多原因,其中之一是匿名类可以直接实现接口:
Runnable r = new Runnable() {
public void run() {}
}
这不是任何东西的子类(而是 Object,但什么不是 Object 的子类......),但它也是一个匿名类。
为什么这个类不称为匿名子类而不是匿名内部类?
因为(通常)匿名内部类不一定是子类1 。 匿名内部类可以扩展接口而不是类。
因为在我们谈论匿名内部类的大多数情况下,“子类性”并不重要2 。
因为人类是懒惰的3并且“匿名内部子类”是一个额外的音节。 或者换句话说,人们有一种自然的倾向来优化他们的演讲和写作模式。
因为……约定俗成。
“内在”从何而来?
Inner 在 Java 中具有技术含义。 这意味着两件事。
this
。请参阅@Andreas 的回答中的不错的分类法。
历史脚注。
事实上,官方术语是匿名类。 事实上,Sun 在 Java 1.1 中使用术语“匿名类”而不是“匿名内部类”,当时该构造被添加到语言中。 例如,Java 1.1.4 发行说明中的“内部类规范”将它们称为“匿名类”……大多数情况下。
我怀疑发生的事情是 Sun 早期的演讲或论文中存在一些不一致之处,并且许多非 Sun 的作者在他们的作品中都使用了“匿名内部阶级”版本。 Sun 团队试图通过使用官方 Java 语言规范和教程中的“匿名类”来悄悄地纠正这个问题。 但为时已晚。 书在书店,文章在网上。
1 - 除了微不足道的意义。 这不是Object每个类必须有一些类的子类。
2 - 同样,您通常会说“我要带狗散步”,而不是“我要带黑色拉布拉多犬散步”。
3 - 在这种情况下,“好懒惰”。
要回答您的问题的标题,是的,它们是。 匿名内部类实际上是子类。
“由于它是用类型 A 声明的,匿名类 [Obj] 必须是 A 的子类。”
做得好。 :)
无论如何,要回答为什么存在“内部”:如果您在另一个类中声明一个匿名类(并且匿名类不是静态声明的,更多内容见下文),那么它将能够像访问它一样访问其周围的类内部类会。 例如:
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
的底层类和类RegularInner
都可以访问Outer
的字段,以及属于Outer
其他特定于实例的内容。 这就是匿名类有时可能被称为“内部”类的原因。
内部类的任何实例都需要使用外部类的实例来创建以支持它,否则它将不知道它属于哪个对象(不是类)。
如果匿名类被声明为static
,它将无法访问其周围类的内容,也不会是“内部”类(相反,它将是匿名“嵌套”类)。
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);
}
}
请记住,匿名类可以是“内部”或“嵌套”的。 因此,当一般谈论它们时,只需说“匿名类”。 (匿名内部类是一种匿名类)。 另外,请务必阅读评论,因为它们给出了大部分解释。
任何问题? :)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.