在Java中组合通用类型

4
我在一个意想不到的情况下遇到了类型不匹配错误。
public interface I {}

public abstract class C {}

public class A extends C implements I {}

public class B extends C implements I {}

public class Foo {

    public <T extends C & I> T getComposition(String selector) {
        switch (selector) {
            case "a": return new A(); // type-mismatch!
            case "b": return new B(); // type-mismatch!
        }
    }

}

为什么既是C又是IA不能作为T返回?


5
如果我这样调用你的方法foo.<Hello>getComposition(),这个方法应该返回一个Hello类的实例,但它返回了一个A类的实例。A继承了CI接口,而T也是同样。但这并不意味着TA是同一个类。 - JB Nizet
我错过了!谢谢@JBNizet。 - Giovanni Lovato
@JBNizet 那个解释很有道理,但您能指出一些关于泛型这方面的进一步阅读材料吗?至少从我的角度来看,如果您在答案中提供这些内容,我会点赞的;-) - GhostCat
@GiovanniLovato 的原因是 Test.class 是类型为 Class<C> 的。你不能将类型为 Class<C> 的引用分配给类型为 Class<T> 的变量,因为它们不是同一种东西。 - Raj S. Rusia
http://stackoverflow.com/a/32659085/2158288 - ZhongYu
显示剩余2条评论
2个回答

4

符号<T extends C & I>的意思是T是一个类型参数。这意味着当有人调用函数时,他们必须指定这个类型。唯一的限制是该类型必须扩展CIA就是这样一种类型,但我可以创建一个新类,它也可以扩展CI。就像这个例子:

class B extends C implements I {}

Foo foo = new Foo();
B b = foo.<B>getComposition();

如果你的示例编译通过,这将导致异常,因为A不是与B相同的类型。

如果你真的只想返回一个A,你需要删除泛型参数并直接使返回类型为A。像这样:

public class Foo {
    public A getComposition() {
        return new A();
    }
}

有没有一种使用泛型表达“something”的方法,但是其中包含new A() - GhostCat
@GhostCat 我真的不明白为什么这个方法一开始就是通用的。它不应该是通用的,它的返回类型应该只是 A。我意识到实际情况可能更加复杂,但我们对此一无所知。 - JB Nizet
@JBNizet 我已经更新了示例,使其更类似于实际情况(当然仍然只是一个示例)。 - Giovanni Lovato
如果我理解正确的话,你并不想使你的方法成为通用的。你想做的是返回一个实现了I接口并且扩展了C类的类型。你应该要么创建两个方法(一个返回I,一个返回C),要么创建一个抽象类Foo,它扩展了C并实现了I,并确保A和B都扩展了Foo。 - JB Nizet

1
你说的是对的,但只是一部分。A或B是T,这是绝对正确的。但T本身并不是A或B。例如,我有另一个名为D的类,它扩展了A。因此,D也是T。如果你说T是A,那么你也意味着D是A。这完全不正确,因为D是A的子类型。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接