这两个声明有什么区别?
声明一:
ArrayList<String> arrayList = new ArrayList<String>();
声明 2:
List<String> arrayList = new ArrayList<String>();
List<String> arrayList = new ArrayList<String>();
是通用的,您希望在将实现细节返回给客户端时隐藏实现细节,稍后您可以将实现从透明更改ArrayList
为LinkedList
透明。
这种机制在您设计库等的情况下很有用,这可能会在某个时间点更改它们的实现细节,而客户端的更改最少。
ArrayList<String> arrayList = new ArrayList<String>();
这要求您始终需要返回ArrayList
。在某个时间点,如果您想将实现细节更改为LinkedList
,客户端也应该进行更改以使用LinkedList
而不是ArrayList
.
List
是一个接口,ArrayList
是 List 接口的一个实现。除了 List 接口中可用的方法之外,该类ArrayList
只有几个方法(i.e clone(), trimToSize(), removeRange() and ensureCapacity())
。这没有太大区别。
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<>();
否则,您将应该在所有地方进行更改,无论您使用特定的类实现作为方法参数。
不同之处在于变体 1 强制你使用ArrayList
while 变体 2 只保证你有任何实现的东西List<String>
。
稍后您可以轻松地将其更改为List<String> arrayList = new LinkedList<String>();
。变体 1 可能不仅需要更改该行,还需要更改其他部分(如果它们依赖于使用ArrayList<String>
.
因此,我List<String>
几乎在任何情况下都会使用,除非我需要调用ArrayList
提供的附加方法(迄今为止从未如此):ensureCapacity(int)
和trimToSize()
.
第一个声明必须是 ArrayList,第二个可以轻松更改为另一种 List 类型。因此,第二个是首选,因为它清楚地表明您不需要特定的实现。(有时您确实需要一种实现,但这种情况很少见)
基本上,它允许 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(...));
从中得出的主要结论是,您要指定要装箱的对象类型。
至于 using Object l = new ArrayList<>();
,您没有访问List
orArrayList
实现,因此您无法对集合做太多事情。
很容易将实现更改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
List 是接口,ArrayList 是实现的具体类。始终建议使用。
List<String> arrayList = new ArrayList<String>();
因为这里的列表引用是灵活的。它也可以容纳LinkedList or Vector
物体。
在某些情况下,您可能更喜欢第一种来(稍微)提高性能,例如在一些没有 JIT 编译器的JVM 上。
在那种非常具体的上下文中,您应该使用第一个。
可能你可以参考这个链接 http://docs.oracle.com/javase/6/docs/api/java/util/List.html
List是一个接口。ArrayList,LinkedList等是实现list的类。当你使用List接口时,你必须使用ListIterator迭代元素并且可以向前和向后移动,在List中就像在ArrayList中使用Iterator迭代并且它的元素可以访问单向方式。
每当您看到来自 Guava 等开源社区和 Google Developer(Android 库)的编码时,他们都会使用这种方法
List<String> strings = new ArrayList<String>();
因为它对用户隐藏了实现细节。你正是
List<String> strings = new ArrayList<String>();
这是通用方法和这种专门的方法
ArrayList<String> strings = new ArrayList<String>();
供参考:Effective Java 2nd Edition:Item 52:通过接口引用对象