在下面的示例中,如果列表中有多个类型,则编译正常,但如果我有一个元素,则会选择不再可分配的其他类型.
// compiles fine
List<Class<? extends Reference>> list = Arrays.asList(SoftReference.class, WeakReference.class);
// but take an element away and it no longer compiles.
List<Class<? extends Reference>> list2 = Arrays.asList(WeakReference.class);
// without giving the specific type desired.
List<Class<? extends Reference>> list3 = Arrays.<Class<? extends Reference>>asList(WeakReference.class);
Run Code Online (Sandbox Code Playgroud)
我确信这有一个合乎逻辑的解释,但它逃脱了我.
Error:Error:line (30)error: incompatible types
required: List<Class<? extends Reference>>
found: List<Class<WeakReference>>
Run Code Online (Sandbox Code Playgroud)
为什么有两个元素编译但一个元素没有?
顺便说一句:如果你试试,很难找到一个简单的例子
List<Class<? extends List>> list = Arrays.asList(ArrayList.class, LinkedList.class);
Error:Error:line (28)error: incompatible types
required: List<Class<? extends List>>
found: List<Class<? extends INT#1>>
where INT#1 is an intersection type:
INT#1 extends AbstractList,Cloneable,Serializable
Run Code Online (Sandbox Code Playgroud)
这也不编译(它甚至不会解析)
List<Class<? extends AbstractList & Cloneable & Serializable>> list = Arrays.asList(ArrayList.class, LinkedList.class);
Error:Error:line (30)error: > expected
Error:Error:line (30)error: ';' expected
Run Code Online (Sandbox Code Playgroud)
但是编译得很好
static abstract class MyList<T> implements List<T> { }
List<Class<? extends List>> list =
Arrays.asList(ArrayList.class, LinkedList.class, MyList.class);
List<Class<? extends List>> list =
Arrays.<Class<? extends List>>asList(ArrayList.class, LinkedList.class);
Run Code Online (Sandbox Code Playgroud)
编辑:基于Marko的例子.在这四个示例中,一个不编译,其余的生成相同类型的相同列表.
List<Class<? extends Reference>> list = new ArrayList<>();
list.add(SoftReference.class);
list.add(WeakReference.class);
list.add(PhantomReference.class);
List<Class<? extends Reference>> list = new ArrayList<>(
Arrays.asList(SoftReference.class));
list.add(WeakReference.class);
list.add(PhantomReference.class);
List<Class<? extends Reference>> list = new ArrayList<>(
Arrays.asList(SoftReference.class, WeakReference.class));
list.add(PhantomReference.class);
List<Class<? extends Reference>> list = new ArrayList<>(
Arrays.asList(SoftReference.class, WeakReference.class, PhantomReference.class));
Run Code Online (Sandbox Code Playgroud)
Ted*_*opp 14
有趣的问题.我认为这是怎么回事.当你有两个像你显示的元素时,返回类型asList是所有参数的最具体类型,在你的第一个例子中List<Reference>.这与分配兼容List<? extends Reference>.当您有一个参数时,返回类型是参数的特定类型,它不是赋值兼容的,因为泛型不是协变的.
考虑
// ok
List<Object> list3 = Arrays.asList(new Object(), new String());
// fail
List<Object> list4 = Arrays.asList(new String());
Run Code Online (Sandbox Code Playgroud)
第二个例子尝试将a分配List<String>给a List<Object>,失败了.
第二个例子可以工作,如果javac查看周围的上下文,考虑目标类型,并推断出T=Object在这里工作.Java 8可能会这样做(我不确定)
只有在一种情况下,javac(java 5)才会使用上下文信息进行类型推断,请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12. 2.8
我们可以利用它来制定解决方法
public static <R, T extends R> List<R> toList(T... elements)
{
return Arrays.asList((R[])elements);
}
Run Code Online (Sandbox Code Playgroud)
现在他们可以编译:
List<Object> list4 = toList(new String());
List<Class<? extends Reference>> list = toList(SoftReference.class, WeakReference.class);
List<Class<? extends Reference>> list2 = toList(WeakReference.class);
Run Code Online (Sandbox Code Playgroud)
这是因为R无法从参数类型推断出,并且方法结果位于赋值上下文中,因此javac会尝试R按目标类型进行推断.
这适用于赋值或返回语句
List<Class<? extends Reference>> foo()
{
return toList(WeakReference.class); // "subject to assignment conversion"
}
Run Code Online (Sandbox Code Playgroud)
否则它将不起作用
void bar(List<Class<? extends Reference>> list){...}
bar( toList(WeakReference.class) ); // fail; R not inferred
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11264 次 |
| 最近记录: |