Java 与数组不兼容的类型。asList()

Java 与数组不兼容的类型。asList(),java,generics,Java,Generics,在下面的示例中,如果列表中有多个类型,它将编译为ok,但如果有一个元素,它将选择一个不再可分配的不同类型 // 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<

在下面的示例中,如果列表中有多个类型,它将编译为ok,但如果有一个元素,它将选择一个不再可分配的不同类型

// 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);
//编译得很好

列出有趣的问题。我想是这样的。当有两个类似于show的元素时,
asList
的返回类型是所有参数中最具体的类型,在第一个示例中是
List
。这是与
列表兼容的作业这很有趣:

where INT#1 is an intersection type:
INT#1 extends AbstractList,Cloneable,Serializable
也许这就是(某些)问题的原因

元素的相交类型可能不是唯一确定的。当您声明自己的列表时,数组的交集类型被确定为
list


使用
数组时。对这种行为有两个部分的解释:

  • 右手边的类型如何随着参数的变化而变化
  • 为什么某些RHS类型与LHS类型不兼容
  • 1.右手边
    asList
    的签名为

    <T> List<T> asList(T... a)
    

    asList(WeakReference.class、SoftReference.class)
    ->列表考虑

        // ok
        List<Object> list3 = Arrays.asList(new Object(), new String());
        // fail
        List<Object> list4 = Arrays.asList(new String());
    
    现在可以对它们进行编译:

        List<Object> list4 = toList(new String());
    
        List<Class<? extends Reference>> list = toList(SoftReference.class, WeakReference.class);
    
        List<Class<? extends Reference>> list2 = toList(WeakReference.class);
    
    否则就不行了

    void bar(List<Class<? extends Reference>> list){...}
    
    bar( toList(WeakReference.class) ); // fail; R not inferred
    

    void条(列表我认为jdk<7中的编译器要求语句的两部分具有相同的声明。也不是100%确定这是导致问题的原因!!我正在使用Java 7 update 9。然后,我认为您要么在语句的两侧添加相同的声明,要么在第二部分中根本不声明它。@mamdouhalramadan I ag这是我发现的一种变通方法。我很想知道为什么隐式铸造的规则在不同的情况下会有所不同。所有这些情况对我来说都是有意义的,我仍然看不到你想要在工作和非工作情况之间造成的紧张。
    Class
    is-not-a
    Class@PeterLawrey-哦,错了,我是说“协变”。更新了答案。在我看来,隐式强制转换的规则在不同的情况下是不同的。一定有某种逻辑说,可以用asList强制转换一种方式,但不能用赋值。@PeterLawrey-计算交集(编译器只需调用
    asList
    )从来都不是问题——最坏的情况下,你最终得到的是
    Object
    。不过,毫不奇怪,赋值语句中解析泛型的规则与方法调用的规则不同。或者我误解了你的观点了吗?@PeterLawrey-我的措辞是错误的。规则相同,但情况不同,因此规则适用。每个实际参数都被分配给一个参数,该参数是所有实际参数的交集类型。根据交集类型的定义,这几乎不会导致问题。另一方面,赋值语句将交集类型分配给代码指定的泛型类型。这时n可能是个问题(在这种情况下,因为泛型类型不是协变的).这种解释在几个方面是错误的:首先,
    List
    的赋值与
    List+1兼容,我同意这就是为什么我以限制类型交叉的方式创建了虚拟MyList。+1,这是正确答案。关键在JLS§15.12.2.8的第一行:如果该方法的任何类型参数不是从实际参数的类型推断出来的,那么现在将按如下方式推断它们……”因为在
    Arrays.asList()的情况下,返回列表的类型是从实际参数推断出来的
    ,上下文推断的规则不适用。您仍然需要将
    @SuppressWarnings(“unchecked”)
    添加到
    toList
    方法中。没有它,我将为varargs参数创建
    未经检查的泛型数组
    警告。
    列表4=toList(新字符串());
    无法编译(不兼容类型)。请修正您的答案。您的
    列表
    方法有问题。从
    数组返回的
    列表
    。asList
    由传入的数组支持。如果将
    对象
    放入列表中,您有一个
    列表
    ,它会引发
    数组异常
    。请参阅。
    where INT#1 is an intersection type:
    INT#1 extends AbstractList,Cloneable,Serializable
    
    List<Class<? extends Reference>> list2 = Arrays.asList(WeakReference.class);
    
    List<Class<? extends Reference>> list3 = Arrays.<Class<? extends Reference>>asList(WeakReference.class);
    
    <T> List<T> asList(T... a)
    
    asList(WeakReference.class) -> List<Class<WeakReference>>
    
    asList(WeakReference.class, SoftReference.class) 
       -> List<Class<? extends Reference>>
    
    List<Class<WeakReference>> lw = new ArrayList<>();
    List<Class<? extends Reference>> lq = lw;
    lq.add(PhantomReference.class);
    
        // ok
        List<Object> list3 = Arrays.asList(new Object(), new String());
        // fail
        List<Object> list4 = Arrays.asList(new String());
    
    public static <R, T extends R> List<R> toList(T... elements)
    {
        return Arrays.asList((R[])elements);
    }
    
        List<Object> list4 = toList(new String());
    
        List<Class<? extends Reference>> list = toList(SoftReference.class, WeakReference.class);
    
        List<Class<? extends Reference>> list2 = toList(WeakReference.class);
    
    List<Class<? extends Reference>> foo()
    {
        return toList(WeakReference.class);  // "subject to assignment conversion"
    }
    
    void bar(List<Class<? extends Reference>> list){...}
    
    bar( toList(WeakReference.class) ); // fail; R not inferred