我最近想了解更多有关通用方法的知识,并创建了几个示例,但以下类型的安全性对我来说并不清楚。这是一个例子:
public class GeneralMethod
{
public static void main( String[] args )
{
Repository rep = new Repository();
Set<ConcreteObject> set = rep.getObject();
}
}
abstract class AbstractRepository
{
public abstract <T extends SuperObject> Set<T> getObject();
}
class Repository extends AbstractRepository
{
@Override
public Set<ConcreteObject> getObject() //<- Type safety!
{
return new HashSet<ConcreteObject>();
}
}
abstract class SuperObject
{
}
class ConcreteObject extends SuperObject
{
}
以下类型安全出现在eclipse中的Repository.class
:
Type safety: The return type Set < ConcreteObject > for getObject() from the type Repository needs checked conversion to conform to Set < SuperObject > from the type AbstractRepository
为什么编译器要符合Set < SuperObject > instead of Set < T extends Superobject >
?
您如何告诉每个存储库使用自己的类型实现getObject()
方法,并且只使用方法签名中的泛型? (意思是没有在类签名中定义泛型)。
答案 0 :(得分:4)
如何使用方法签名中仅使用泛型来告诉每个Repository实现具有自己类型的getObject()方法? (意思是没有在类签名中定义泛型)。
你做不到。当你说“它是自己的类型”时,你会指的是Repository子类的泛型类型 - 除非你做FooRepository extends AbstractRepository<Foo>
之类的事情,否则它不存在。
在这种情况下,我只是将抽象类设为通用:
public abstract class AbstractRepository<T extends SuperObject>
abstract Set<T> getObjects();
}
BTW,没有非抽象方法的抽象类可能更好地设计为接口。
答案 1 :(得分:1)
AbstractRepository repository = new Repository();
Set<SuperObject> set = repository.getObject();
那应该编译,但你可以Set<ConcreteObject>
分配给Set<SuperObject>
变量。
返回Set<? extends SuperObject>
应编译[未测试]。您可能希望使基类具有通用性(或者根本不返回集合)。
答案 2 :(得分:1)
“为什么编译器要符合Set&lt; SuperObject&gt;而不是Set&lt; T extends Superobject&gt;?”
因为你这么告诉他了! 在所有Superobject之后,可替代T的最少类型是。答案 3 :(得分:1)
class AbstractRepository
Set<? extends SuperObject> getObject();
class Repository extends AbstractRepository
Set< ConcreteObject > getObject()
这是有效的,因为Set<ConcreteObject>
是Set<? extends SuperObject>
答案 4 :(得分:0)
T extends SuperObject
将T
绑定到extends
(是SuperObject
的子类AbstractRepository.getObject()
的任何类。您正在覆盖class Repository extends AbstractRepository
{
@Override
public Set<T extends SuperObject> getObject() //Valid
{
return new HashSet<ConcreteObject>();
}
}
方法,因此方法签名必须与其父类相同。
这应该是有效的(未经测试)
{{1}}