假设A是一个自定义类,请考虑以下匿名内部类的声明:
A Obj = new A() {
@Override
public String toString() {
return "Hello!";
}
}
在这种情况下,Obj是匿名内部类的实例,该内部类的toString方法已被覆盖。由于它是用类型A声明的,因此匿名类必须是A的子类。那么,为什么不将此类称为匿名子类而不是匿名内部类呢? “内在”来自哪里?
答案 0 :(得分:4)
是的,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 :(得分:3)
为什么此类不称为匿名子类而不是匿名内部类?
因为(通常)匿名内部类不一定是子类 1 。匿名内部类可以扩展接口,而不是类。
因为在我们谈论匿名内部类的大多数情况下,“子类性质”并不重要 2 。
因为人类是懒惰的 3 ,所以“匿名内部子类”是另外一个音节。换句话说,人们自然会优化他们的言语和写作方式。
因为...约定。
“内部”来自哪里?
Inner在Java中具有技术含义。这意味着两件事。
this
。在@Andreas的答案中查看不错的分类法。
历史脚注。
实际上,官方术语是匿名类。实际上,早在Java 1.1中,当将构造添加到语言时,Sun就使用术语“匿名类”而不是“匿名内部类”。例如,Java 1.1.4发行说明中的"Inner Class Specification"经常将它们称为“匿名类”。
我怀疑发生的事情是早期的Sun演示文稿或论文中存在一些不一致之处,并且各种非Sun的作者在其著作中都使用了“匿名内部类”版本。 Sun团队尝试通过使用官方Java语言规范和教程中的“匿名类”来悄悄地纠正此问题。但为时已晚。这些书在书店里,文章在网上。
1-在琐碎的意义上除外。每个不是Object的类都必须是 some 类的子类。
2-同样,您通常会说“我要带狗去散步”,而不是“我要带黑色拉布拉多去散步”。
3-在这种情况下,“好懒”。
答案 2 :(得分:2)
子类和内部类是匿名类的两个不同方面。由于语法的原因,匿名类显然是命名类的子类,因此 inner 方面与分类更为相关。
Java类是这样的类别, 1 :
如您所见,匿名类是内部嵌套类。
分类未指定该类是子类,基类还是独立类。任何类别的类都可以是子类或基类。与ernest_k mentioned in another answer一样,可以从接口定义匿名类,在这种情况下,它根本不是子类。
1)在this other answer末尾摘录更大的层次结构。
答案 3 :(得分:1)
是的,要回答您问题的标题。匿名内部类实际上是子类。
“由于声明了类型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);
}
}
请记住,匿名类可以是“内部” OR “嵌套”。因此,通常在谈论它们时,只需说“匿名类”即可。 (匿名内部类是匿名类的一种)。另外,请务必阅读注释,因为它们会给出大多数解释。
有什么问题吗? :)