抽象类与接口是否可以实例化

抽象类与接口简介

具体的就不说了,直说一下二者的重要的相同点和区别:

相同点:

  • 都是抽象的(不能正常实例化的)
  • 都可以有抽象方法
  • 都可以有成员变量

区别:

  • 抽象类除了不能正常实例化和可以含有抽象方法外其他特性与普通类相同
  • 抽象类既可以有抽象方法也可以有普通的方法,而接口只能包含抽象方法
  • 抽象类可以只声明成员变量而不初始化,接口必须在声明成员方法时初始化

不能实例化

以前我一直认为抽象类和接口是不能被初始化的, 意思就是不能使用new关键字来获取类的实例(接口也算是一个类),如:

1
TestInterface inter = new TestInterface();

当TestInterface是一个抽象类或者接口时,上述代码将会产生编译时错误.

但是当我在学习鸿洋的一篇关于Android中RecyclerView的博客时发现他对一个接口使用了new关键字
原文链接请点击:Android中RecyclerView
这让我不得不重新思考接口和抽象类到底能否实例化,还是仅仅不能用上述的普通方法来实例化,
于是有了下面的一段测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class test { 

public test() {
TestInterface inter = new TestInterface() {
public void myTestInterface() {
System.out.println("run method myTestInterface");
}
};

TestAbstract abs = new TestAbstract() {
public void myTestAbstract() {
System.out.println("run method myTestAbstract");
}
};
inter.myTestInterface();
abs.myTestAbstract();
abs.print();
}

public static void main(String[] args) {
test t = new test();
}
}

interface TestInterface {
public void myTestInterface();
}

abstract class TestAbstract {
public abstract void myTestAbstract();
public void print() {
System.out.println("run method print");
}
}

执行结果为:

1
2
3
run method myTestInterface
run method myTestAbstract
run method print

所以是可以对抽象类和接口使用new关键字的,但是在初始化的时候还是需要去实现抽象类和接口中所定义的抽象方法
那么这到底是算是对抽象了和接口实例化了吗?

个人想法

以下是个人想法,有待验证,如果错误请指出
java之所以不允许以正常方式使用new关键字来实例化抽象类和接口,是因为其中定义了抽象方法,
既然有抽象方法,那么即使你获取了抽象类和接口的实例,这些抽象方法也没有具体的实现(方法内容),也是没有意义的.
但即使你删除上面测试代码中抽象类所定义的抽象方法myTestAbstract()之后,只保留抽象类的具体方法print(),
依然无法对TestAbstract抽象类进行普通实例化,所以java应该是认为只要是抽象类和接口都是不能被正常实例化的.

而上述代码又确实使用new关键字进行了实例化,但是请注意,上述代码在实例化时,
实现了抽象类和接口所定义的抽象方法,所以关键字new后面的类型已经不能算是原来的抽象类和接口了,
它已经是一个具体的类了,而不是抽象的了,因为原来的抽象类和接口里的抽象方法是没有方法体的,
也就是没有具体内容的, 当你在一个”类”中实现了这些抽象方法,那么这个类就已经不是原来的”类”了.
所以上述代码之所以能够正常运行,是因为new关键字所获取的类的实例并不是抽象类或接口的实例.
因而”抽象类和接口不能被实例化”这句话是正确的
所以按照上面测试中的方法对抽象类和接口使用new关键字与上面这句话并不冲突.