【问题标题】:Why do I get a Type safety warning here? (generics)为什么我会在这里收到类型安全警告? (泛型)
【发布时间】:2011-03-25 13:30:57
【问题描述】:

我最近想了解更多有关泛型方法的信息并创建了几个示例,但我不清楚以下类型安全性。举个例子:

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 &lt; ConcreteObject &gt; for getObject() from the type Repository needs checked conversion to conform to Set &lt; SuperObject &gt; from the type AbstractRepository

为什么编译器要符合Set &lt; SuperObject &gt; instead of Set &lt; T extends Superobject &gt;

你会如何告诉每个 Repository 用自己的类型实现 getObject() 方法,并且只在方法签名中使用泛型? (意思是没有在类签名中定义泛型)。

谢谢你, 梅内

【问题讨论】:

    标签: java generics


    【解决方案1】:

    你会如何告诉每个 Repository 用自己的类型实现一个 getObject() 方法,只在方法签名中使用泛型? (意思是没有在类签名中定义泛型)。

    你不能。当您说“它是自己的类型”时,您指的是 Repository 子类的泛型类型 - 除非您正在执行类似 FooRepository extends AbstractRepository&lt;Foo&gt; 的操作,否则它不存在。

    在这种情况下,我会简单地将抽象类设为泛型:

    public abstract class AbstractRepository<T extends SuperObject>
          abstract Set<T> getObjects();
    }
    

    顺便说一句,没有非抽象方法的抽象类可能更好地设计为接口。

    【讨论】:

    • Idd,在没有泛型类的情况下尝试它的原因是,真正的抽象类已经有两个泛型,所以我不会为单个方法添加第三个,因为它可能会混淆更多比它有帮助。也许我只需要重新考虑该方法的当前类设计。谢谢!
    【解决方案2】:
    class AbstractRepository
    
      Set<? extends SuperObject> getObject();
    
    
    class Repository extends AbstractRepository
    
      Set<    ConcreteObject   > getObject()
    

    这是因为Set&lt;ConcreteObject&gt;Set&lt;? extends SuperObject&gt; 的子类型

    另见Overriding method with generic return type

    【讨论】:

    • 对不起,我的回复晚了,但谢谢。这正是我想要的!
    【解决方案3】:
    AbstractRepository repository = new Repository();
    Set<SuperObject> set = repository.getObject();
    

    这应该可以编译,但您会将Set&lt;ConcreteObject&gt; 分配给Set&lt;SuperObject&gt; 变量。

    返回Set&lt;? extends SuperObject&gt; 应该编译[未测试]。您可能希望使基类通用(或根本不返回集合)。

    【讨论】:

    • 示例已经编译。我只是不太清楚,为什么会有警告。 Idd 更好的解决方案可能是使基类通用。只是想避免它,因为原始基类已经有两个泛型。
    • 编译,我的意思是编译没有警告。
    【解决方案4】:

    “为什么编译器要符合Set而不是Set?”

    因为你是这么告诉他的! 毕竟,可以替代 T 的最少类型是 Superobject。

    【讨论】:

    • 哦,好的,我不太清楚,谢谢。我以为这样我会告诉编译器我明确想要一个扩展 SuperObject 的类。
    【解决方案5】:

    T extends SuperObjectT 绑定到extends(是SuperObject 的子类)的任何类。您正在覆盖 AbstractRepository.getObject() 方法,因此方法签名必须与其父类相同。

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

    class Repository extends AbstractRepository
    {
      @Override
      public Set<T extends SuperObject> getObject() //Valid
      {
        return new HashSet<ConcreteObject>();
      }
    }
    

    【讨论】:

    • 不幸的是它无效,因为你不能在方法返回类型中使用'T extends xxx'。但感谢您的努力。
    • @ymene,不幸的是,您的代码就是这样设置的。如果你想知道具体的返回类型,你可以让你的类通用。
    猜你喜欢
    • 2021-03-27
    • 1970-01-01
    • 2021-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多