在声明变量/参数时,使用ArrayList或LinkedList而不是List是正确的吗?

时间:2013-09-24 20:33:58

标签: java

假设你有一个类似的东西:

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接口?如果是的话,何时?

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

7 个答案:

答案 0 :(得分:3)

通常,您应该只使用接口List来声明您的结构。但是,在极少数情况下,您需要使用仅适用于List的某个实现的特定方法,例如LinkedListArrayList,那么您应该明确声明您的列表类型。但是,这限制了灵活性,应该谨慎地进行。

答案 1 :(得分:1)

这不是ArrayList/LinkedList的示例,但我认为返回List的方法可能很好地声明如下:

public ImmutableList doSomething();

其中ImmutableList是番石榴的ImmutableList。这种声明清楚地表明返回的列表不是要修改的,因此它是通过代码而不是注释传递的(或者在运行时尝试修改列表时只有异常)。

答案 2 :(得分:1)

如果您想为用户定义他们可以期待的效果,那么简单的答案就是

基本上,如果您正在处理的只是一个List并且它与哪种列表无关紧要,那么您只是打算迭代它,然后将其声明为List

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

答案 3 :(得分:1)

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

这使您的代码可以以您无法想象的方式工作。

正如我们在Collection框架中,我写了一些我在编码时使用的建议。

如果我不需要知道我使用Iterable界面的大小。这允许我使用foreach,我可以在以后传递不同于java集合框架的各种类型。

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

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

当我需要操作独特的物品时,我使用Set界面。

一般情况下,我会以迭代开始,然后将其更改为其他类型,但这些只是一些规则而不是规则。

答案 4 :(得分:1)

您可能希望确保List-Interface未授予列表的某个属性。在下面的示例中,您可能传入一个不可Seralizable的List,导致序列化类时出现Runtime-Error。 :

public class foo implements Serializable{

private List<String> fooThings;

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

}

ArrayList实现Serializable。还有其他方法可以确保列表可以通过通用方法进行Seralizable,例如

public <T extends List & Serializable> setFooThings(T things) 

答案 5 :(得分:0)

您始终希望将变量声明为:

private List<String> fooThings;

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

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

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

答案 6 :(得分: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
    }
}

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

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

代码接口 - 灵活/松散耦合代码。 实施准则 - 用于特殊操作。