众所周知,arraylist是init。应该是这样的

ArrayList<A> a = new ArrayList<A>();
ArrayList<Integer> a = new ArrayList<Number>(); // compile-time error

那么,为什么Java允许这些?
1. ArrayList<? extends Object> a1 = new ArrayList<Object>();
2. ArrayList<?> a2 = new ArrayList<Integer>();

那么,如果它们是正确的,为什么不允许这些?
1. a1.add(3);
2. a2.add(3);

编译器消息是:ArrayList类型中的方法add(int,capture#1-of?extended Object)不适用于参数(int)

更一般
  1. a1.add(null e);
  2. a2.add(? e);

我读到了有关此事,但很高兴收到您的来信。谢谢

另一个有趣的地方是:
 ArrayList<ArrayList<?>> a = new ArrayList<ArrayList<?>>(); // correct
 ArrayList<?> a = new ArrayList<?>(); // wrong. I know it's reason but I have some
question in my mind that mentioned above

最佳答案

您不能将List<Number>分配给List<Integer>类型的引用,因为List<Number>允许使用Integer以外的数字类型。如果允许您这样做,则将允许以下操作:

List<Number> numbers = new ArrayList<Number>();
numbers.add(1.1); // add a double
List<Integer> ints = numbers;
Integer fail = ints.get(0); // ClassCastException!
List<Integer>类型可以保证它包含的任何内容都是Integer。这就是为什么您可以不进行强制转换就从其中获取Integer的原因。如您所见,如果编译器允许将其他类型的List(例如Number)分配给List<Integer>,则保证会被破坏。

List<Integer>分配给诸如List<?>List<? extends Number>之类的类型的引用是合法的,因为?表示“给定类型的某些未知子类型”(对于Object而言,类型是?;对于Number而言,类型是? extends Number)。

由于?表示您不知道List将接受哪种特定类型的对象,因此除了null之外,都不能添加任何其他对象。但是,允许您从其中检索任何对象,这是使用? extends X限制通配符类型的目的。请注意,对于? super X有界通配符类型而言,情况恰恰相反... List<? super Integer>是“至少是Integer的父类(super class)型的某种未知类型的列表”。尽管您不确定确切的List类型(可以是List<Integer>List<Number>List<Object>),但您确实知道无论是哪​​种类型,都可以将Integer添加到其中。

最后,new ArrayList<?>()是不合法的,因为当您创建像ArrayList这样的参数化类的实例时,必须提供一个特定的类型参数。您可以在示例中使用任何内容(ObjectFoo都没有关系),因为除了null之外,您将无法再添加其他任何内容,因为您是直接将其分配给ArrayList<?>引用。

07-24 09:46
查看更多