我们能否使用AbstractList代替List接口来持有一个ArrayList实例?

3

通常我们使用代码来进行接口:

List<String> list  = new ArrayList<String>();

我们可以这样写吗?
AbstractList<String> list  = new ArrayList<String>();

这种初始化方式有什么缺点?欢迎提供任何见解。

在进行这样的操作之前,您应该了解协变性和逆变性可能存在的问题(例如:https://dev59.com/VnE95IYBdhLWcg3wApHk)。 - realbart
4个回答

5
定义列表为AbstractList会将你的实现与AbstractList的子类绑定在一起,而使用List接口允许你将任意实现该接口的实现分配给list变量。
将列表定义为AbstractList也将使你可以访问AbstractList的方法(无需进行强制类型转换),这些方法不是List接口的一部分,但使用它们会使你的代码变得不够灵活。
如果没有非常好的理由,请不要这样做。

1
主要的缺点是通用的:在Java中,你一次只能继承一个类,但可以实现任意多个接口。
如果list是私有或本地变量,则初始化为接口几乎没有优势。最好使用:
ArrayList<String> list  = new ArrayList<String>();

然而,如果您有一个公共字段或方法参数,最好使用最少特定声明:接口。抽象类也实现了接口,因此可以使用它。但是您的类的消费者随后可以使用实现接口的任何类,而该类可以继承任何其他他们可能喜欢的类。


1
使用 List<String> 而不是 AbstractList<String> 的优点在于,List 指定了一个合同,而 AbstractList 指定了(部分)实现。使用 List 确保您的代码与任何 List 的实现兼容,而不仅仅是从 AbstractList 派生的实现。
尽管在变量声明方面遵循这种做法可能看起来并不像什么大不了的事情,但在整个代码中遵循这种用法可以确保应用程序具有更大的灵活性。

0

使用AbstractList的一个缺点是,您限制了自己只能使用扩展AbstractList的列表类。实现List接口而不将AbstractList作为超类是完全可能的。

第二个缺点是这样不会编译:

List<String> list = new ArrayList<String>();

AbstractList<String> list2 = list;

Java类型系统不允许您假设每个List<String>都是一个AbstractList<String>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接