这两个声明之间有什么区别?
声明1:
ArrayList<String> arrayList = new ArrayList<String>();
声明2:
List<String> arrayList = new ArrayList<String>();
答案 0 :(得分:56)
List<String> arrayList = new ArrayList<String>();
在您将实现详细信息返回给客户端时隐藏实现详细信息的通用名称,稍后您可以透明地将实现从ArrayList
更改为LinkedList
。
这种机制在您设计库等的情况下非常有用,这可能会在某些时候更改其实现细节,而客户端的更改很少。
ArrayList<String> arrayList = new ArrayList<String>();
这要求您始终需要返回ArrayList
。在某些时候,如果您希望将实施细节更改为LinkedList
,则客户端也应进行更改,以使用LinkedList
代替ArrayList
。
答案 1 :(得分:11)
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
,则需要在一点上进行更改only(实例化部分)。
List<String> l = new LinkedList<>();
否则,您应该在所有地方进行更改,无论您在哪里使用特定的类实现作为方法参数。
答案 2 :(得分:6)
不同之处在于变体1强制您使用ArrayList
,而变体2仅保证您拥有实现List<String>
的任何内容。
稍后您可以毫不费力地将其更改为List<String> arrayList = new LinkedList<String>();
。变体1可能要求您不仅要更改该行,还要更改其他部分,如果他们依赖于使用ArrayList<String>
。
因此,我几乎在任何情况下都使用List<String>
,除非我需要调用ArrayList
提供的其他方法(到目前为止从未如此):{{1} }和ensureCapacity(int)
。
答案 3 :(得分:2)
第一个声明必须是ArrayList,第二个声明可以很容易地更改为另一个List类型。因此,第二个是首选,因为它清楚地表明您不需要特定的实现。 (有时你确实需要一个实现,但这很少见)
答案 4 :(得分:2)
很容易将实施更改为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
答案 5 :(得分:2)
基本上,它允许Java通过泛型类型声明(如class MyStructure<T extends TT>
)在一个结构实现中存储多种类型的对象,这是Javas的主要功能之一。
面向对象的方法基于模块化和可重用性,通过关注点分离 - 将结构与任何类型的对象一起使用的能力(只要它遵守一些规则)。
您可以实例化以下内容:
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");
如果您想查看一些示例,请查看文档documentation:
/**
* 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<>();
,您无法访问List
或ArrayList
实施,因此您无法对该集合做太多工作。
答案 6 :(得分:1)
List是接口,ArrayList是实现的具体类。 始终建议使用。
List<String> arrayList = new ArrayList<String>();
因为这里列表参考是灵活的。它还可以保存LinkedList or Vector
对象。
答案 7 :(得分:1)
在某些情况下,您可能更喜欢第一个(略微)提高性能,例如在某些JVM without a JIT compiler上。
在这种非常具体的背景下,你应该使用第一个。
答案 8 :(得分:1)
您可以参考此链接 http://docs.oracle.com/javase/6/docs/api/java/util/List.html
List是一个接口.ArrayList,LinkedList等是实现list的类。当你使用List接口时,你必须使用ListIterator迭代元素并且可以在List中向前和向后移动,在Array中使用Iterator迭代它。元素可以单向访问。
答案 9 :(得分:0)
每当您看到像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:通过接口引用对象