为什么我在这里收到类型安全警告? (泛型)

时间:2011-03-25 13:30:57

标签: java generics

我最近想了解更多有关通用方法的知识,并创建了几个示例,但以下类型的安全性对我来说并不清楚。这是一个例子:

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()方法,并且只使用方法签名中的泛型? (意思是没有在类签名中定义泛型)。

谢谢你, ymene

5 个答案:

答案 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>

的子类型

另见Overriding method with generic return type

答案 4 :(得分:0)

T extends SuperObjectT绑定到extends(是SuperObject的子类AbstractRepository.getObject()的任何类。您正在覆盖class Repository extends AbstractRepository { @Override public Set<T extends SuperObject> getObject() //Valid { return new HashSet<ConcreteObject>(); } } 方法,因此方法签名必须与其父类相同。

这应该是有效的(未经测试)

{{1}}