答案:
不能!!
背景:
最近有同事跟我说了他面试时遇到的问题,考官问:“接口和抽象类可以被new嘛?”。这可能不是考官的原话,但是据他表达考官大概就是这个意思了。听到这个问题,我的第一反应是肯定不行啊,直接对接口和抽象类调用new,编译器都过不去。但是他说,考官说可以,用匿名内部类实现。听见这个回到,我感觉那个考官太………,有点无语。我们可以仔细分析下这个问题。
直接new接口和抽象类
首先先明确一点,直接new接口和抽象类,这肯定行不通,编译器会提示Cannot instantiate the type XX的错误。这个实验就不做了,没意思。
且接口是特殊的抽象类(所以,接口只是抽象类的一种)
使用匿名内部类
下面的代码是一个匿名内部类的Demo,也就是考官说的可以new。
(匿名内部类方式还可以参考文章:Java中抽象类有构造方法可以直接new对象_小贝520-CSDN博客_抽象类可以new对象)
package com.saillen.test;
interface A {
void f();
}public class T {
public T(A a) {
a.f();
}public static void main(String[] args) {
T t = new T(new A() {
public void f() {
System.out.println("我是匿名内部类");
System.out.println("Class对象是:" + this.getClass());
System.out.println("类名字是:" + this.getClass().getSimpleName());
}
});
}}
上面的程序很简单,我们使用匿名内部类,然后“new”一个接口A的对象,输出它的类名了Class对象,输出如下:
1 我是匿名内部类 2 Class对象是:class com.saillen.test.T$1 3 类名字是:
通过输出可以看到,内部类的类名是“”也就是一个空字符串,但是它确确实实是有类型的。而且查看编译后的class文件,会发现,会多一个T$1.class,这个class就是匿名内部类的原型,
用javap反编译这个文件,可以看到这个类的源码样式如下:
通过反编译后的文件可以证明,我们的“匿名内部类”的类名是Test$1。所以new针对的还是普通的class(虽然内部类和普通类有很大不一样),只不过这个class的写法稍有不同,它是编译器帮我们从匿名内部类中提取的。
那么回归问题本质,什么是抽象类?
抽象:就是不具体的意思。类是对对象的具体描述,而抽象类不具体,没有方法体,(提供的成员不足以生成一个具体对象),那么就无法生成一个不具体的对象。
就好比,
你可以实例化一个苹果,但你不能实例化一个水果(这个现实中存在的实物)。
比如定义一个动物类接口。这个接口是所有动物所共有的特点组成在一起,但是并不能组成现实中真真正正存在的物种。
结论:
通过上面的实验,当然是,接口和抽象类不可以被new!即不可以被实例化!
匿名内部类只是一种写法上的迷惑而已。这个考官的答案很不靠谱,不能说他的想法就是绝对的错,但是绝对不应该这么问这个问题,这不是一个能不能就回答的。或者说不能从字面上就证明可以对interface或者abstract class使用new。