这里,我正在创建我的类的实例
不,您不是在这里创建抽象类的实例。相反,您是在创建抽象类的匿名子类的实例。然后在指向子类对象的抽象类引用上调用方法。
这种行为在JLS -章节# 15.9.1中明确列出:-
If the class instance creation expression ends in a class body, then
the class being instantiated is an anonymous class. Then:
If T denotes a class, then an anonymous direct subclass of the class named by T is declared. It is a compile-time error if the
class denoted by T is a final class.
If T denotes an interface, then an anonymous direct subclass of Object that implements the interface named by T is declared.
In either case, the body of the subclass is the ClassBody given in the class instance creation expression.
The class being instantiated is the anonymous subclass.
我特别强调。
此外,在JLS -第12.5节中,您可以阅读到关于对象创建过程的内容。我在这里引用其中的一段话:-
每当创建一个新的类实例时,就分配内存空间
为该类中声明的所有实例变量留出空间
类的每个超类中声明的所有实例变量
类类型,包括可能隐藏的所有实例变量。
控件返回对新创建对象的引用之前
结果,则处理指定的构造函数以初始化new
对象,使用以下过程:
你可以在我提供的链接上阅读完整的程序。
要实际看到被实例化的类是一个匿名子类,您只需要编译两个类。假设你把这些类放在两个不同的文件中:
My.java:
abstract class My {
public void myMethod() {
System.out.print("Abstract");
}
}
Poly.java:
class Poly extends My {
public static void main(String a[]) {
My m = new My() {};
m.myMethod();
}
}
现在,编译两个源文件:
javac My.java Poly.java
现在在你编译源代码的目录中,你会看到以下类文件:
My.class
Poly$1.class // Class file corresponding to anonymous subclass
Poly.class
看那个类- Poly$1.class。它是编译器创建的类文件,对应于你使用下面的代码实例化的匿名子类:
new My() {};
很明显,有一个不同的类被实例化了。只是,这个类只有在编译器编译后才会被赋予名称。
一般来说,类中的所有匿名子类都将以这种方式命名:
Poly$1.class, Poly$2.class, Poly$3.class, ... so on
这些数字表示这些匿名类在外围类中出现的顺序。