Java泛型:List,List<;对象>;,列表<&燃气轮机;

Java泛型:List,List<;对象>;,列表<&燃气轮机;,java,generics,Java,Generics,有人能尽可能详细地解释一下以下类型之间的区别吗 List List<Object> List<?> 列表 列表 列表 让我更具体一点。我想什么时候使用 // 1 public void CanYouGiveMeAnAnswer(List l) { } // 2 public void CanYouGiveMeAnAnswer(List<Object> l) { } // 3 public void CanYouGiveMeAnAnswer(List&

有人能尽可能详细地解释一下以下类型之间的区别吗

List
List<Object>
List<?>
列表
列表
列表
让我更具体一点。我想什么时候使用

// 1 
public void CanYouGiveMeAnAnswer(List l) { }

// 2
public void CanYouGiveMeAnAnswer(List<Object> l) { }

// 3
public void CanYouGiveMeAnAnswer(List<?> l) { }
//1
公共无效不能给出答案(列表l){}
// 2
公共无效不能给出答案(列表l){}
// 3
公共无效不能给出答案(列表l){}

我建议您参考Sun Microsystems提供的优秀和优秀产品。另一个很好的资源是这本书。

为了补充Rob提到的教程,这里有一本wikibook解释这个主题:


编辑:

  • 对列表中项目的类型没有限制

  • 列表中的项必须扩展对象

  • 通配符本身使用,因此它匹配任何内容


  • 在这一点上,我得出几乎没有任何区别的结论是天真的吗?

    最简单的解释不是“RTFM”:

    将生成大量编译器警告,但主要等效于:

    List<Object>
    
    列表
    
    而:

    List<?>
    
    列表
    
    基本上意味着它是泛型的,但是你不知道泛型类型是什么。当您无法修改刚刚返回列表的其他内容的返回类型时,它非常有助于消除编译器警告。其更有用的形式是:

    List<? extends SomeOtherThing>
    

    List最简短的解释是:第二项是可以容纳任何类型的列表,您可以向其中添加对象:

    List<Object>
    
    第三个列表可以容纳任何类型,但不能向其中添加任何内容:

    List<?> 
    
    列表
    

    基本上,当您真正拥有一个可以包含任何对象的列表并且希望能够向列表中添加元素时,可以使用第二种形式(
    List
    )。当您将列表作为方法返回值接收时,您将使用第三种形式(
    List
    ),并且您将在列表上迭代,但从不向其添加任何内容。永远不要使用第一种形式(
    List
    )在Java 5或更高版本下的新代码编译中。

    我这样说:虽然
    List
    List
    可以包含任何类型的对象,
    List
    包含未知类型的元素,但一旦捕获该类型,它就只能包含该类型的元素。这就是为什么它是这三种类型中唯一的类型安全变体,因此通常更可取。

    简单地说:

    名单

    将声明一个普通集合,可以保存任何类型,并且将始终返回对象

    名单

    将创建一个列表,该列表可以容纳任何类型的对象,但只能分配给另一个列表

    例如,这不起作用

    List<Object> l = new ArrayList<String>();
    
    listl=newarraylist();
    
    当然,您可以添加任何内容,但只能拖动对象

    List<Object> l = new ArrayList<Object>();
    
    l.add( new Employee() );
    l.add( new String() );
    
    Object o = l.get( 0 );
    Object o2 = l.get( 1 );
    
    listl=newarraylist();
    l、 添加(新员工());
    l、 添加(新字符串());
    对象o=l.get(0);
    对象o2=l.get(1);
    
    最后

    名单

    将允许您分配任何类型,包括

    List <?> l = new ArrayList(); 
    List <?> l2 = new ArrayList<String>();
    
    listl=newarraylist();
    列表l2=新的ArrayList();
    
    这将被称为未知集合,因为未知的公共分母是对象,所以您将能够获取对象(巧合)

    当unknown与子类一起使用时,它的重要性就来了:

    List<? extends Collection> l = new ArrayList<TreeSet>(); // compiles
    
    List<? extends Collection> l = new ArrayList<String>(); // doesn't,
    // because String is not part of *Collection* inheritance tree. 
    
    列表
    我想什么时候使用

    // 1 
    public void CanYouGiveMeAnAnswer(List l) { }
    
    // 2
    public void CanYouGiveMeAnAnswer(List<Object> l) { }
    
    // 3
    public void CanYouGiveMeAnAnswer(List<?> l) { }
    
    当你不能做所有的铸造你自己

    我想什么时候使用

    // 1 
    public void CanYouGiveMeAnAnswer(List l) { }
    
    // 2
    public void CanYouGiveMeAnAnswer(List<Object> l) { }
    
    // 3
    public void CanYouGiveMeAnAnswer(List<?> l) { }
    
    public void不能给出答案(列表l){
    
    当您要限制列表的类型时。例如,这将是一个无效的参数

     new ArrayList<String>();
    
    newarraylist();
    
    我想什么时候使用

    // 1 
    public void CanYouGiveMeAnAnswer(List l) { }
    
    // 2
    public void CanYouGiveMeAnAnswer(List<Object> l) { }
    
    // 3
    public void CanYouGiveMeAnAnswer(List<?> l) { }
    
    public void不能给出答案(列表l){
    

    绝大多数情况下是不会的。

    正如其他帖子所指出的,您正在询问一个名为泛型的Java特性。在C++中,这称为模板。java中的这个特性通常比C++中的更容易使用。 让我从功能上回答你的问题(如果这不是OO讨论的顽皮词汇的话)

    在泛型之前,有像Vector这样的具体类

    Vector V = new Vector();
    
    向量包含你给它们的任何对象

    V.add("This is an element");
    V.add(new Integer(2));
    v.add(new Hashtable());
    
    它们通过将给定给它的所有值转换为一个对象(所有Java类的根)来实现这一点。当您试图检索存储在向量中的值时,您需要将该值转换回原始类(如果您想对其执行任何有意义的操作)

    演员很快就变老了。除此之外,编译器还会向您抱怨未经检查的强制转换。这种强制转换最紧迫的问题是,向量的使用者必须在编译时知道其值的类,才能正确地强制转换。在向量的生产者和消费者彼此完全隔离的情况下(想想RPC消息),这可能是一个致命的问题

    输入泛型。泛型尝试创建强类型类来执行泛型操作

    ArrayList<String> aList = new ArrayList<String>();
    aList.add("One");
    String element = aList.get(0); // no cast needed
    System.out.println("Got one: " + element); 
    
    您应该将其理解为“L是一种处理字符串对象的列表”。当您开始处理工厂类时,处理契约而不是特定实现是至关重要的。工厂在运行时生成各种类型的对象

    使用泛型非常容易(大多数时候)

    有一天,您可能会决定要实现自己的泛型类。也许您想编写一个新的数据库抽象接口,以消除各种数据存储之间的差异。定义泛型类时,将使用
    作为将由方法操作的对象类型的占位符

    如果您仍然感到困惑,请使用列表的泛型类,直到您感到满意为止。稍后,您可以更加自信地深入实现。或者,您可以查看JRE附带的各种列表类的源代码。开源就是这样

    看看甲骨文/太阳报。
    干杯。

    要在这里添加已经很好的答案:

    方法参数:V.add("This is an element"); V.add(new Integer(2)); v.add(new Hashtable());
    String s = (String) v.get(0);
    Integer i = (Integer) v.get(1);
    Hashtable h = (Hashtable) v.get(2);
    
    ArrayList<String> aList = new ArrayList<String>();
    aList.add("One");
    String element = aList.get(0); // no cast needed
    System.out.println("Got one: " + element); 
    
    List<String> L = new ArrayList<String>();
    
    List<Foo> foos= new ArrayList<Foo>();
    
    foos.add(new Bar()); // NOT OK!
    
    List<Object> objs = new ArrayList<Object>();
    objs.add(new Foo());
    objs.add(new Bar());
    
    List<Object> objs = foos; // NOT OK!
    
    List<?> dontKnows = foos;
    
    dontKnows.add(new Foo()); // NOT OK
    dontKnows.add(new Bar()); // NOT OK
    
    List rawList = new ArrayList();
    rawList.add("String Item");
    rawList.add(new Car("VW"));
    rawList.add(new Runnable() {
                @Override
                public void run() {
                   // do some work.
                }
            });
    
       Object item = rawList.get(0); // we get object without casting.
       String sameItem = (String) rawList.get(0); // we can use casting which may fail at runtime.
    
    List<String> stringsList = new ArrayList<>();
    stringsList.add("Apple");
    stringsList.add("Ball");
    stringsList.add(new Car("Fiat")); //error
    String stringItem = stringsList.get(0);
    
     List<Object> objectList = new ArrayList<Object>();
     objectList.add("String Item");
     objectList.add(new Car("VW"));
     objectList.add(new Runnable() {
            @Override
            public void run() {
    
            }
     });
     Object item = objectList.get(0); // we get object without casting as list contains Object
     String sameItem = (String) objectList.get(0); // we can use casting which may fail at runtime.
    
    List<String> tempStringList = new ArrayList<>();
    rawList = tempStringList; // Ok as we can assign any list to raw list.
    objectList = tempStringList; // error as List<String> is not subtype of List<Obejct> becuase generics are not convariant.
    
    List<?> crazyList = new ArrayList<String>();
     List<String> stringsList = new ArrayList<>();
     stringsList.add("Apple");
     stringsList.add("Ball");
     crazyList = stringsList; // fine
    
    List<?> crazyList = new ArrayList<?>(); // any list.
    
    List<?> crazyList2 = new ArrayList<String>();
    
    crazyList2.add("Apple"); // error as you dont actually know what is that type.
    
     public static void print(List<?> list){
            System.out.println(list);
        }