Java中的类型列表与类型ArrayList (1)List myList=new ArrayList(); (2) ArrayList myList=新的ArrayList();

Java中的类型列表与类型ArrayList (1)List myList=new ArrayList(); (2) ArrayList myList=新的ArrayList();,java,list,interface,decoupling,Java,List,Interface,Decoupling,我知道使用(1),可以交换列表接口的实现。似乎(1)通常在应用程序中使用,而不考虑需要(我自己,我总是使用它) 我想知道是否有人使用(2) 此外,这种情况实际需要使用(1)而不是(2)的频率有多高(我能举个例子吗)(即,除了对接口进行编码和最佳实践等之外,几乎总是列表比数组列表更受欢迎,例如,列表可以在不影响代码库其余部分的情况下转换为 如果使用ArrayList而不是List,则很难将ArrayList实现更改为LinkedList实现,因为在代码库中使用了ArrayList特定方法,这也需要

我知道使用(1),可以交换列表接口的实现。似乎(1)通常在应用程序中使用,而不考虑需要(我自己,我总是使用它)

我想知道是否有人使用(2)


此外,这种情况实际需要使用(1)而不是(2)的频率有多高(我能举个例子吗)(即,除了对接口进行编码和最佳实践等之外,

几乎总是
列表
数组列表
更受欢迎,例如,
列表
可以在不影响代码库其余部分的情况下转换为

如果使用
ArrayList
而不是
List
,则很难将
ArrayList
实现更改为
LinkedList
实现,因为在代码库中使用了
ArrayList
特定方法,这也需要重新构造

您可以阅读
列表
实现


您可以从一个
数组列表开始,但很快就会发现另一个实现是更合适的选择。

我认为1是首选,除非

  • 您取决于ArrayList中可选行为*的实现,在这种情况下,显式使用ArrayList更为明确
  • 您将在需要ArrayList的方法调用中使用ArrayList,可能是为了可选的行为或性能特征
我的猜测是,在99%的情况下,你可以通过列表,这是首选

  • 例如
    removeAll
    ,或
    add(null)
我想知道是否有人使用(2)

对。但很少有合理的理由(IMO)

人们被烧死是因为他们在应该使用列表的时候使用了数组列表:

  • Collections.singletonList(…)
    Arrays.asList(…)
    这样的实用方法不会返回
    ArrayList

  • List
    API中的方法不保证返回相同类型的列表

例如,有人被烧伤,海报中的“切片”有问题,因为
ArrayList.sublist(…)
不返回
ArrayList
。。。他设计的代码使用
ArrayList
作为所有列表变量的类型。他最终通过将子列表复制到新的
ArrayList
中“解决”了这个问题

您需要知道
列表
的行为的参数主要通过使用
随机访问
标记接口来解决。是的,它有点笨重,但另一种更糟

此外,这种情况实际需要使用(1)而不是(2)的频率有多高(即,除了“接口编码”和最佳实践等之外,(2)还不够)

这个问题的“频率”部分客观上是无法回答的

(我能举个例子吗)

有时,应用程序可能要求您使用
ArrayList
API中不在
列表中的方法。例如,
ensureCapacity(int)
trimToSize()
removeRange(int,int)
。(只有创建了将方法声明为
public
的ArrayList子类型时,才会出现最后一个)

这是向类而不是接口编码的唯一合理理由,IMO

(从理论上讲,在某些情况下,在某些平台上,性能可能会略有提高……但除非你真的需要最后的0.05%,否则这样做是不值得的。我认为,这不是一个合理的理由。)


如果不知道随机访问是否有效,就无法编写高效的代码

这是一个正确的观点。然而,Java提供了更好的方法来处理这个问题;e、 g

(1) List<?> myList = new ArrayList<?>();

(2) ArrayList<?> myList = new ArrayList<?>();
公共无效测试(T列表){
//做事
}
如果您使用未实现
RandomAccess
的列表调用它,您将得到一个编译错误

您还可以动态测试。。。使用
instanceof
。。。如果静态输入太笨拙。您甚至可以编写代码来使用不同的算法(动态),这取决于列表是否支持随机访问

请注意,
ArrayList
并不是实现
RandomAccess
的唯一列表类。其他包括
CopyOnWriteList
Stack
Vector

我见过人们对
Serializable
(因为
List
没有实现它)提出同样的观点。。。但上述方法也解决了这个问题。(在某种程度上,它可以使用运行时类型来解决。如果任何元素不可序列化,
ArrayList
将无法序列化。)

(3)Collection myCollection=new ArrayList();

我通常使用这个。只有当我需要列表方法时,我才会使用列表。ArrayList也一样。您总是可以切换到更“窄”的界面,但不能切换到更“宽”的界面。

我知道(2)可以更好的唯一情况是使用GWT,因为它减少了应用程序占用空间(这不是我的想法,但google web toolkit团队这么说)。但是对于在JVM中运行的常规java来说(1)可能总是更好。

我认为使用(2)的人不知道或。或者他们真的必须使用
ArrayList

如果code是列表的“所有者”,我就使用(2)。例如,这对于仅局部变量是正确的。没有理由使用抽象类型
List
而不是
ArrayList
。 证明所有权的另一个例子:

public <T extends List & RandomAccess> void test(T list) {
    // do stuff
}
公共类测试{
//此对象是的所有者
public class Test {

    // This object is the owner of strings, so use the concrete type.
    private final ArrayList<String> strings = new ArrayList<>();

    // This object uses the argument but doesn't own it, so use abstract type.
    public void addStrings(List<String> add) {
        strings.addAll(add);
    }

    // Here we return the list but we do not give ownership away, so use abstract type. This also allows to create optionally an unmodifiable list.
    public List<String> getStrings() {
        return Collections.unmodifiableList(strings);
    }

    // Here we create a new list and give ownership to the caller. Use concrete type.
    public ArrayList<String> getStringsCopy() {
        return new ArrayList<>(strings);
    }
}
List list = new ArrayList(100); // will be better also to set the initial capacity of a collection 
ArrayList list = new ArrayList();
(1) List<?> myList = new ArrayList<?>();
(2) ArrayList<?> myList = new ArrayList<?>();
public class ExampleData implements java.io.Serializable {

// The following also guarantees that strings is always an ArrayList.
private final ArrayList<String> strings = new ArrayList<>();
public static void main(String[] args) {
    List<String> list = new ArrayList<String>();
    list.add("a");
    list.add("b");

    ArrayList<String> aList = new ArrayList<String>();
    aList.add("a");
    aList.add("b");

}
   L0
    LINENUMBER 9 L0
    NEW ArrayList
    DUP
    INVOKESPECIAL ArrayList.<init> () : void
    ASTORE 1
   L1
    LINENUMBER 10 L1
    ALOAD 1: list
    LDC "a"
    INVOKEINTERFACE List.add (Object) : boolean
    POP
   L2
    LINENUMBER 11 L2
    ALOAD 1: list
    LDC "b"
    INVOKEINTERFACE List.add (Object) : boolean
    POP
   L3
    LINENUMBER 13 L3
    NEW java/util/ArrayList
    DUP
    INVOKESPECIAL java/util/ArrayList.<init> ()V
    ASTORE 2
   L4
    LINENUMBER 14 L4
    ALOAD 2
    LDC "a"
    INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
    POP
   L5
    LINENUMBER 15 L5
    ALOAD 2
    LDC "b"
    INVOKEVIRTUAL java/util/ArrayList.add (Ljava/lang/Object;)Z
    POP
ArrayList<Object> myMethod (ArrayList<Object> input) {
   // body
}
List<Object> myMethod (List<Object> input) {
   // body
}
List<Object> list = new ArrayList<Object> ();

list.add ("string");

myMethod (list);