Java泛型编译错误 - 类型< type>中的方法方法(Class< capture#1-of?extends Interface>)不适用于论据 [英] Java generics compilation error - The method method(Class<capture#1-of ? extends Interface>) in the type <type> is not applicable for the arguments

查看:3922
本文介绍了Java泛型编译错误 - 类型< type>中的方法方法(Class< capture#1-of?extends Interface>)不适用于论据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上个星期四,有人在工作中向我展示了一个编译错误,我无法用一种干净的方式修复它,并且一直困扰着我。

问题是泛型相关的,我重建了一个简化版本的代码,它会产生编译错误。该错误发生在下面显示的最后一行代码中。



我一直在寻找遍布所有的interwebs,但似乎无法找到一个体面的解释为什么Java编译器不接受代码。我猜如果是允许代码的话,可能会在Bar.operationOnBar()中创建一个类演员问题,但我不明白。



有人请指教我为什么不能编译?

  public interface接口{
}


public class Type implements Interface {
}

public class Bar< T> {
public Bar(Class< T> clazz){
}

public void operationOnBar(Class< T> arg){
}
}

公共类Foo {
public< T>巴≤; T> bar(Class< T> clazz){
返回新的Bar< T>(clazz);
}
public static void main(String [] args){
Class< ;?扩展界面> extendsInterfaceClazz = Type.class;
new Foo().bar(extendsInterfaceClazz).operationOnBar(Type.class);





$ b

Foo第二行编译错误.main():

 方法operationOnBar(Class   

顺便说一句。我已经通过将Type.class向下转换为Class来解决此问题,这样编译器无法看到Class的泛型类型是Type而不是?extends Interface。

List< T>替换有问题的泛型类 解决方案

code>。然后很容易找到一个破坏类型安全的例子。



这个替换是正确的,因为目前Java没有提供任何关于可能的先验知识的方法泛型类的行为(即,它缺少一种方法来指定泛型类在其声明中的协变性和变异性,就像在C#4和Scala中一样)。因此,编译器就其可能的行为而言是 Class < / code>和 List< T> 必须禁止可能导致其他泛型类的 List< T> 出现问题的转换。

在您的案例:

  public class Bar< T> {
私人列表< T>升;

public Bar(List< T> l){
this.l = 1;
}

public void operationOnBar(List< T> arg){
l.addAll(arg);
}
}

列表< Type1> l1 = new ArrayList< Type1>();
列表< ;?扩展界面> l2 = l1;
列表< Type2> l3 = Arrays.asList(new Type2());

new Foo()。bar(l2).operationOnBar(l3);

Type1 t = l1.get(0); //哎呀!


Last Thursday someone at work showed me a compile error that I wasn't able to fix in a clean way and it has been bothering me ever since.

The problem is generics related and I've reconstructed a simplified version of the code that generates the compile error. The error occurs in the very last line of code shown below.

I've been looking all over the interwebs but can't seem to find a decent explanation why the Java compiler doesn't accept the code. I guess that if it were to allow the code, it would be possible the create a class cast issue in Bar.operationOnBar(), but I don't see how.

Could someone please enlighten me why this doesn't compile?

public interface Interface {
}


public class Type implements Interface {
}

public class Bar<T> {
    public Bar(Class<T> clazz) {
    }

    public void operationOnBar(Class<T> arg){
    }
}

public class Foo {
    public <T> Bar<T> bar(Class<T> clazz){
        return new Bar<T>(clazz);
    }
    public static void main(String[] args) {
        Class<? extends Interface> extendsInterfaceClazz = Type.class;
        new Foo().bar(extendsInterfaceClazz).operationOnBar(Type.class);
    }
}

Compile Error on the second line of Foo.main():

The method operationOnBar(Class<capture#1-of ? extends Interface>) in the type Bar<capture#1-of ? extends Interface> is not applicable for the arguments (Class<Type>)

Btw. I've solved it by downcasting Type.class to Class, this way the compiler is unable to see that the generic type of Class is "Type" instead of "? extends Interface".

解决方案

A little advice: when you are not sure why compiler prohibits some generic-related conversion, replace generic classes in question with List<T>. Then it would be easy to find an example that breaks type safety.

This replacement is correct since currently Java doesn't provide a way to conduct any a priory knowledge about possible behaviours of generic classes (i.e. it lacks a way to specify covariance and contravariance of generic classes in their declarations, as in C# 4 and Scala). Therefore Class<T> and List<T> are equivalent for the compiler with respect to their possible behaviours, and compiler has to prohibit conversions that can cause problems with List<T> for other generic classes as well.

In your case:

public class Bar<T> {
    private List<T> l;

    public Bar(List<T> l) {
        this.l = l;
    }

    public void operationOnBar(List<T> arg) {
        l.addAll(arg);
    }
}

List<Type1> l1 = new ArrayList<Type1>();
List<? extends Interface> l2 = l1;
List<Type2> l3 = Arrays.asList(new Type2());

new Foo().bar(l2).operationOnBar(l3);

Type1 t = l1.get(0); // Oops!

这篇关于Java泛型编译错误 - 类型&lt; type&gt;中的方法方法(Class&lt; capture#1-of?extends Interface&gt;)不适用于论据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆