这个基本的通用示例真的无法实现吗?

时间:2012-07-13 12:45:20

标签: java generics

昨天看到这篇文章:How I instantiate? Include code

用户无法获取泛型类的构造函数类型X,以匹配传递给构造函数IA的对象的类型,即使<X extends IA>

我并不是非常喜欢提供的唯一答案,因为如果你必须将M构造函数类型从X更改为IA<X>,那么泛型的全部意义就无济于事。当然这就是为什么M的泛型类型是<X extends IA> ??

对于这个基本的例子,真的没有办法使用泛型(没有任何被抑制的警告)吗?

public interface IA<X extends IA<X>>{}

public class A<X extends IA<X>> implements IA<X>{}

public class W<X extends IA<X>>{}

public class M<X extends IA<X>> extends W<X>{
    X anx;

    public M(X x){} //Type X here is not compatibile with IA in the test code
}


//Testing code in a different class
public <X extends IA<X>> void check() {

    IA<X> a = new A<X>();
    W<X> s = new M<X>(a); //Doesn't compile because IA<X> is not the same as 'X', even though <X extends IA> 
    W<X> s = new M(a);    //Compiles, but with suppressed warnings

    X a = new A<X>();  //Doesnt compiler (ignoring dupicate 'a' variable)  
    W<X> s = new M<X>(a); compiles
}

编辑以包括IA到处包括'extends'

3 个答案:

答案 0 :(得分:2)

你必须做这样的事情:

//Testing code in a different class
public <X extends IA<X>> void check() {
    IA<X> a = new A<X>();
    W<subtypeofIA(IA works as well)> s = new M<subtypeofIA(IA works as well)>(a); //Doesn't compile because IA<X> is not the same as 'X', even though <X extends IA> 
    W<X> s = new M(a);    //Compiles, but with suppressed warnings 
}

关于警告,我认为它们是不言自明的,它们可以概括为:当你想要使用一般参数化类型时,你必须将泛型参数实例化为具体类型。引入了通用参数以概括代码,但也强制类型安全。使用IA意味着你扔掉了你可以说的类型安全:IA&lt; ASpecificType&gt;并且编译器会引起你的注意。

以下代码是我能够接近您的代码并且同时具有一定意义的代码:

interface IA<X extends IA<X>>{}

class A<X extends IA<X>> implements IA<X>{}

class W<X extends IA<X>>{}

class M<X extends IA<X>> extends W<X>{
    X anx;

    public M(X x){} //Type X here is not compatibile with IA in the test code 
}


//Testing code in a different class
public <X extends IA<X>> void check() {

    IA<X> a = new A<X>();
    W<X> s = new M<X>(null); //Doesn't compile because IA<X> is not the same as 'X', even though <X extends IA> 
    W<X> ss = new M(a);    //Compiles, but with suppressed warnings

    X aa = new A<X>();  //this is completely illegal  
    W<X> sss = new M<X>(aa); //compiles
}

答案 1 :(得分:1)

这个问题涉及许多没有意义的通用约束。 M<X>的构造函数接受类型为X的参数,这是泛型方法check的类型参数(这意味着调用者可以将X决定为任何内容需要仍然工作)。那么为什么你期望a(或其他任何事情)成为正确的类型?

如果你想问一下如何更改泛型约束以使其有效,这里有一个更简单的事情(它只是改变了泛型(但保持WM原样)而没有别的从原始的)编译,并可能更接近你想要的东西:

public interface IA<X>{}

public class A implements IA<A>{}

public class W<X extends IA<X>>{}

public class M<X extends IA<X>> extends W<X>{
    X anx;

    public M(X x){}
}


public void check() {

    A a = new A();
    W<A> s = new M<A>(a);
}

答案 2 :(得分:0)

问题是,传递给构造函数的a是IA类型。 M的构造函数需要X. IA不能转换为X,因此这是语法错误。

第二个选项是编译,但是如果你实际运行它,你会将amx分配给一个实际上不是X实例的变量(因此你会得到警告说这是一个坏主意)。

如果你改变构造函数以接受IA,那么一切正常。