5

假设您有一个类似的课程:

public class foo {
    private List<String> fooThings;

    public void doSomething(List<String> things) {
        // Do a bunch of things here
        // Possibly setting fooThings at some point as well
    }
}

声明是否适合指定具体类,例如 ArrayList 而不是 List 接口?如果有,什么时候?

编辑> 这个问题与何时使用 LinkedList 以及何时使用 ArrayList 无关。这是一个单独的问题,在其他地方得到了回答。问题是关于什么时候声明应该是接口(List)以便清楚起见,什么时候应该指定一个实现,例如ArrayList,因为考虑到方法将要做什么或如何利用实例变量,这很重要。

4

7 回答 7

3

通常你应该只使用接口List来声明你的结构。但是,在极少数情况下,您需要使用仅可用于特定实现的特定方法,List例如,LinkedList或者ArrayList您应该显式声明您的列表类型。但是,这限制了灵活性,应谨慎使用。

于 2013-09-24T21:00:10.573 回答
1

这不是 的示例ArrayList/LinkedList,但我认为返回 a 的方法List可以像这样声明:

public ImmutableList doSomething();

ImmutableListGuava 的ImmutableList在哪里。这种声明清楚地表明返回的列表不打算被修改,因此它是通过代码而不是注释来传达的(或者仅在运行时尝试修改列表时出现异常)。

于 2013-09-24T20:43:48.377 回答
1

简单的答案是当您想为您的用户定义他们可以期望的性能时

本质上,如果您正在使用的只是 aList并且它是哪种列表并不重要,假设您只是打算遍历它然后将其声明为 a List

但是,如果您想对列表执行特定操作,例如插入条目或大量获取第 n 个条目,那么让每个人都知道它是什么类型的列表以及性能预期是有意义的。

于 2013-09-24T20:52:48.467 回答
1

使用抽象类型作为方法参数或字段声明是一种很好的做法。

这使您的代码有可能以您尚未想象的方式工作。

因为我们在 Collection 框架中,所以我写了一些我在编码时使用的建议。

如果我不需要知道我使用Iterable接口的包的尺寸。这允许我使用,foreach并且我可以稍后传递不是来自 java 集合框架的各种类型。

如果我需要包的大小,我会使用收集界面。

如果我需要从包中挑选物品,我使用列表界面。

当我需要对独特的项目进行操作时,我使用 Set 界面。

通常我从可迭代开始,稍后我将其更改为其他类型,但这些只是少数例外而不是规则。

于 2013-09-24T21:09:37.390 回答
1

您可能希望确保列表接口未授予的列表的某个属性。在下面的示例中,您可能会传入一个不可序列化的列表,从而在类被序列化时导致运行时错误。:

public class foo implements Serializable{

private List<String> fooThings;

public void setFooThings(List<String> things) {
   fooThings = things;
}

}

ArrayList 实现可序列化。还有其他方法可以通过通用方法确保列表可序列化,例如

public <T extends List & Serializable> setFooThings(T things) 
于 2014-04-30T14:17:14.413 回答
0

您总是希望将变量声明为:

private List<String> fooThings;

这允许我们在实际使用 fooThings 时使用任何类型的列表、LinkedList、ArrayList 等。

您可能会在程序的某些部分使用 LinkedList,然后为另一部分切换到 ArrayList,因为它更适合。我们希望在开发过程中为自己提供最大的灵活性。

我们也可能遇到通过来自另一个类的参数初始化 fooThings 的情况。我们不想将其声明为特定类型的列表,因为这样我们将方法的调用者限制为使用这种特定类型的列表,或者在使用我们的方法之前将其列表类型转换为正确的类型,这会导致不必要的工作。

于 2013-09-24T20:58:15.510 回答
0

写接口而不是实现总是好的。这将为处理实现传递接口的不同具体类型提供灵活性..

您的示例代码的另一个抽象级别是

public class foo {
    private Collection<String> fooThings;

    public void doSomething(Collection<String> things) {
        // Do a bunch of things here
        // Possibly setting fooThings at some point as well
    }
}

优势 - 这将允许您处理不同的具体类型的输入。

缺点 - 它会限制想要使用具体类型的任何特定功能。例如,您可能无法使用特定于 LinkedList 的 getFirst()。

代码到接口 - 灵活/松散耦合的代码。实现代码 - 用于特殊操作。

于 2013-09-24T21:13:47.560 回答