在我的一次面试中,有人问我:“我们是否可以实例化一个抽象类?”
我的回答是:“没有。我们不能”。但是,面试官告诉我:“错了,我们可以。”
我对此进行了一些争论。然后他让我自己在家试试。
abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}
class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}
在这里,我正在创建我的类的实例和调用抽象类的方法。有人能给我解释一下吗?我的面试真的错了吗?
抽象类不能像每个人回答的那样被实例化,这是一个公认的事实。
当程序定义匿名类时,编译器实际上创建了一个具有不同名称的新类(具有EnclosedClassName$n模式,其中n是匿名类号)
所以如果你反编译这个Java类,你会发现如下代码:
my.class
abstract class my {
public void mymethod()
{
System.out.print("Abstract");
}
}
Poly $1.class(匿名类的生成类)
class poly$1 extends my
{
}
ploly.cass
public class poly extends my
{
public static void main(String[] a)
{
my m = new poly.1(); // instance of poly.1 class NOT the abstract my class
m.mymethod();
}
}
你可以观察到:
为什么poly扩展my?这没用……
编译的结果是什么?三个文件:my.class, poly.class和poly$1.class
如果我们可以这样实例化一个抽象类,我们也可以实例化一个接口……奇怪的……
我们可以实例化一个抽象类吗?
不,我们不能。我们可以做的是,创建一个匿名类(这是第三个文件)并实例化它。
那么超类实例化呢?
抽象超类不是由我们实例化的,而是由java实例化的。
编辑:请他测试一下
public static final void main(final String[] args) {
final my m1 = new my() {
};
final my m2 = new my() {
};
System.out.println(m1 == m2);
System.out.println(m1.getClass().toString());
System.out.println(m2.getClass().toString());
}
输出是:
false
class my$1
class my$2