Java 中的 ArrayList 或 List 声明

这两个声明之间的区别是什么?

宣言1:

ArrayList<String> arrayList = new ArrayList<String>();

声明2:

List<String> arrayList = new ArrayList<String>();
255534 次浏览
List<String> arrayList = new ArrayList<String>();

是通用的,您希望在将实现细节返回给客户端时隐藏它,稍后您可以透明地将实现从 ArrayList更改为 LinkedList

这种机制在设计库等时非常有用,这些库可能会在某个时间点更改其实现细节,而客户端的更改非常少。

ArrayList<String> arrayList = new ArrayList<String>();

这要求您总是需要返回 ArrayList。在某个时候,如果您想将实现细节更改为 LinkedList,那么客户端也应该更改为使用 LinkedList而不是 ArrayList

List 是接口,而 ArrayList 是实现具体类的。 总是建议使用。

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

因为这里的列表引用是灵活的。它也可以保存 LinkedList or Vector对象。

区别在于,变体1强制您使用 ArrayList,而变体2只保证您拥有实现 List<String>的任何内容。

之后你可以毫不费力地把它改成 List<String> arrayList = new LinkedList<String>();。变体1可能要求您不仅更改该行,而且还要更改其他部分,如果它们依赖于使用 ArrayList<String>的话。

因此,几乎在任何情况下我都会使用 List<String>,除非需要调用 ArrayList提供的其他方法(到目前为止从未出现过这种情况) : ensureCapacity(int)trimToSize()

第一个声明必须是 ArrayList,第二个声明可以很容易地更改为另一个 List 类型。因此,第二种方法更好,因为它清楚地表明您不需要特定的实现。(有时确实需要一个实现,但这种情况很少)

在一些情况下,您可能希望第一种方法(略微)提高性能,例如在某些 JVM 没有 JIT 编译器上。

在这种非常具体的上下文中,您应该使用第一个。

也许你可以参考这个链接 Http://docs.oracle.com/javase/6/docs/api/java/util/list.html

列表是一个接口。ArrayList、 LinkedList 等是实现列表的类。当你使用列表接口时,你必须使用 ListIterator 来迭代元素,并且可以向前和向后移动,在列表中,就像在数组列表迭代中一样,使用 Iterator 和它的元素可以单向访问。

将实现从 List改为 Set很容易:

Collection<String> stringList = new ArrayList<String>();
//Client side
stringList = new LinkedList<String>();


stringList = new HashSet<String>();
//stringList = new HashSet<>(); java 1.7 and 1.8

基本上,它允许 Java 通过泛型类型声明(如 class MyStructure<T extends TT>)在一个结构实现中存储多种类型的对象,这是 Java 的主要特性之一。

面向对象的方法基于模块化和关注点分离的可重用性——使用任何类型对象的结构的能力(只要它遵守一些规则)。

你可以像下面这样实例化:

ArrayList list = new ArrayList();

而不是

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

通过声明和使用泛型类型,您将通知一个结构它将管理的对象类型,并且编译器将能够通知您是否在该结构中插入了非法类型,例如。比如说:

// this works
List list1 = new ArrayList();
list1.add(1);
list1.add("one");


// does not work
List<String> list2 = new ArrayList<>();
list2.add(1); // compiler error here
list2.add("one");

如果您希望看到一些示例,请查看文档 文件:

/**
* Generic version of the Box class.
* @param <T> the type of the value being boxed
*/
public class Box<T> {
// T stands for "Type"
private T t;


public void set(T t) { this.t = t; }
public T get() { return t; }
}

然后你可以实例化这样的事情:

class Paper  { ... }
class Tissue { ... }


// ...
Box<Paper> boxOfPaper = new Box<>();
boxOfPaper.set(new Paper(...));


Box<Tissue> boxOfTissues = new Box<>();
boxOfTissues.set(new Tissue(...));

从中得出的主要结论是,您要指定要装箱的对象类型。

至于使用 Object l = new ArrayList<>();,您不能访问 ListArrayList实现,因此无法对集合进行太多操作。

List是接口,ArrayList是 List 接口的实现。除了 List 接口中可用的方法之外,ArrayList类只有少数几个方法。这没什么区别。

   1. List<String> l = new ArrayList<>();
2. ArrayList<String> l = new ArrayList<>();

如果使用第一个,则可以调用 List 接口中可用的方法,而不能调用 ArrayList类中可用的新方法。如果您使用第二种方法,那么您可以自由地使用 ArrayList中的所有可用方法。

我认为第一种方法更好,因为在开发 Java 应用程序时,当应该将集合框架对象作为参数传递给方法时,最好采用第一种方法。

List<String> l = new ArrayList<>();
doSomething(l);

在将来,由于性能限制,如果您将实现更改为使用 LinkedList或其他实现 List接口的类,而不是 ArrayList,那么您只需要在一个点(实例化部分)进行更改。

List<String> l = new LinkedList<>();

否则,您将需要在所有位置进行更改,无论您在哪里使用特定的类实现作为方法参数。

每当您看到来自诸如 Guava 和 GoogleDeveloper (Android Library)这样的开源社区的代码时,他们都会使用这种方法

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

因为它对用户隐藏了实现细节。 就是你

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

这是一种通用的方法,而这种特殊的方法

ArrayList<String> strings = new ArrayList<String>();

参考资料: 有效的 Java2nd Edition: 第52项: 通过对象的接口引用对象