2017-02-10 86 views
4

在我不期望的情况下,出现类型不匹配的错误。在Java中编写泛型类型

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! 
     } 
    } 

} 

为什么A,这既是CI,不能返回的T

+5

如果我把你的方法称为'foo。 getComposition()',这个方法应该返回一个'Hello'的实例,但它返回一个'A'的实例。 A扩展C&I.T也是。但这并不意味着T和A是同一班。 –

+0

我错过了!谢谢@JBNizet。 –

+0

@JBNizet这个解释是有道理的,但是你能指出一些关于泛型方面的更多的阅读吗?至少从我的角度来看,如果这将是一个答案,我会upvote,;-) – GhostCat

回答

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(); 
    } 
} 
+0

有没有一种方法来表达这样的“东西”,使用泛型,但与那个'新的A()'在那里? – GhostCat

+0

@GhostCat我不明白为什么这个方法是通用的。它不应该是,它的返回类型应该是A.我意识到真正的情况可能更复杂,但我们对此一无所知。 –

+0

@JBNizet我已经更新了这个例子,使它更类似于真实案例(这仍然只是一个例子)。 –

1

你是对的,但只是一部分。 A或B是T,这是绝对正确的。但T本身不是A或B。例如。我有另一个类D和D扩展A.所以,D也是T。如果你说T是A,你也意味着D是A.这是不正确的,因为D是A的子类型。