如何将列表转换为他们的conrecte实现?

假设我正在使用一个我不知道源代码的库。 它有一个返回List的方法,如下所示:

public List getObjs() { ... } 

我想知道这是不是一个好主意:

 ArrayList objs = (ArrayList) getObjs(); 

例如,如果getObjs()里面的List的具体实现是LinkedList那么会不会出现某种类型的差异?

不,这不是一个好主意。 除非由于某种原因需要ArrayList特定行为,否则应始终使用接口( List )声明列表变量。
此外,如果这样做,您需要确保返回的列表是ArrayList 。 在这种情况下, getObjs()的承诺合约只是返回类型是某种List ,所以你不应该假设其他任何东西。 即使现在返回的ListArrayList ,也没有什么能阻止getObjs()的实现者稍后更改返回的List类型,这会破坏你的代码。

转换为您调用的API定义的返回类型。

如果它说它返回List ,那就是。 不要尝试检索基础类型,因为:

a)它可能随新版本(甚至是通话之间)而变化

b)您无需知道任何实现类。

如果你需要一个ArrayList,那么做new ArrayList

使用接口(List)的重点是隐藏实现细节。 为什么要将其转换为具体实现?

你是对的。 这不是一个好主意。 您需要使用它返回的界面表单。

如果你下载到ArrayList,它会抛出一个ClassCastException,而实际上它是一个LinkedList。 一般来说,如果你没有编写返回你想要向下转换的对象的代码,那么这样做也不是一个好主意。 此外,如果您使用这样的第三方库,他们可能会改变他们在改进代码时返回的内容。 如果你在你的代码中放置这样的downcast,它今天可能会工作,但是当你升级你的libs时,它会突然中断。 并且它在运行时断开而不是编译时间,所以在运行之前你不会知道它的损坏。 这是违反图书馆与您签订合同的问题,只有使用List界面。

它返回List原因是你不必关心它接口的底层。

List接口只是声明对象必须满足的合约,以及如何查询它。 图书馆作者将来可以自由选择ArrayListLinkedList或者LazyDatabasePopulatedList 。 实际上,您可能会在运行时获得不同的实现,具体取决于提供类的实现方式。

只要你有合同要坚持,这就给你带来了很大的自由。 只有说话和提供接口,并尽可能少地处理具体类,还有很多要说的。

您应始终使用界面代替Handle 。 这就是OOP Languages的重点,以便您以后可以在任何实现之间切换。

如果要转换为任何具体类,编译器将警告您可能发生Cast Exception。 如果您非常确定类型,可以使用SuppressWarning

这不是一个好主意,因为您不知道该方法返回的实现方式; 如果它不是ArrayList ,你将得到一个ClassCastException 。 实际上,您不应该关心该方法返回的确切实现。 请改用List界面。

如果由于某种原因,您绝对需要一个ArrayList ,那么创建自己的ArrayList并使用该方法返回的List对其进行初始化:

 ArrayList myOwnList = new ArrayList(getObjs()); 

但是不要这样做,除非你绝对需要一个ArrayList – 因为它效率低下。

你为什么不这样做:

 List objs = getObjs(); 

然后使用该列表。 如果由于某种原因你确实需要一个ArrayList,你总是可以这样做

 ArrayList arrayList = new ArrayList(); arrayList.addAll(objs); 

并与之合作。 但这不是很有效。