Java IntelliJ中具有泛型类型的未选中转换警告

Java IntelliJ中具有泛型类型的未选中转换警告,java,generics,Java,Generics,My IDE(IntelliJ)警告我未经检查的转换: 未经检查的覆盖:返回类型需要未经检查的转换。找到'com.company.Main.Cat',必需'T' 尽管如此,我的代码还是像预期的那样工作。我能做些什么来防止这个警告,还是我的代码有“设计”缺陷 以下MCVE再现了Cat的public Cat copy()中的警告 public static void main( String[] args ) { Cat cat = new Cat( "Mimi&q

My IDE(IntelliJ)警告我未经检查的转换:

未经检查的覆盖:返回类型需要未经检查的转换。找到'com.company.Main.Cat',必需'T'

尽管如此,我的代码还是像预期的那样工作。我能做些什么来防止这个警告,还是我的代码有“设计”缺陷

以下MCVE再现了
Cat
public Cat copy()
中的警告

   public static void main( String[] args )
   {
      Cat cat = new Cat( "Mimi" );
      Cat copyCat = cat.copy();
   }

   public static class Cat extends Animal
   {
      public String name;

      public Cat( final String name )
      {
         this.name = name;
      }

      @Override
      public Cat copy() // Unchecked conversion warning
      {
         return new Cat( this.name );
      }

   }

   public abstract static class Animal
   {
      abstract < T extends Animal > T copy();
   }
publicstaticvoidmain(字符串[]args)
{
猫=新猫(“咪咪”);
Cat copyCat=Cat.copy();
}
公共静态类猫扩展动物
{
公共字符串名称;
公共Cat(最终字符串名称)
{
this.name=名称;
}
@凌驾
public Cat copy()//未检查的转换警告
{
返回新的Cat(this.name);
}
}
公共抽象静态类动物
{
抽象T拷贝();
}

你的
动物。copy
方法是泛型的,建议调用者可以指定他们想要的动物类型。。。但您的实现不是通用的

例如,这里有一个稍微增加和更改的代码版本-注意对
main
方法的更改,该方法仅使用
Animal
作为变量类型,但为
copy
方法指定了一个类型参数:

公共类测试{
公共静态void main(字符串[]args){
动物猫=新猫(“咪咪”);
Dog copyCat=cat.copy();
}
公共静态类猫扩展动物{
公共字符串名称;
公共Cat(最终字符串名称){
this.name=名称;
}
@凌驾
公共Cat副本(){
返回新的Cat(this.name);
}
}
公共抽象静态类Dog扩展了Animal{
}
公共抽象静态类动物{
抽象T拷贝();
}
}
main
方法在没有警告的情况下编译-很好

但在执行时:

Exception in thread "main" java.lang.ClassCastException: Test$Cat cannot be cast to Test$Dog
        at Test.main(Test.java:6)
因此,是的,您的代码存在设计缺陷,并且只在您开始使用的用例中按预期工作。几乎可以肯定的是,您不希望使该方法成为泛型方法。您可以将类设置为泛型,也可以将抽象的
copy
方法声明为returning
Animal

公共抽象静态类动物{
抽象动物复制();
}

现在,这将允许声明
Dog.copy()
返回
Cat
,当然。。。但是它至少很简单。

如果您想要一个通用的
copy()
方法以您所期望的方式工作,我会这样更改两个类:

public abstract static class Animal<T extends Animal> {
   abstract T copy();
}

public static class Cat extends Animal<Cat> {
    public String name;

    public Cat(final String name) {
        this.name = name;
    }

    @Override
    public Cat copy() {
        return new Cat(this.name);
    }
}
没关系。然后,参数的编译时类型告诉编译器预期的结果,并且可以(例如,使用
clone()
)实现一个方法,该方法返回作为其参数得到的同一类的实例

但是用这样的方法

    public <T extends Animal> T copy(T originalAnimal) { ... }
    public <T extends Animal> T copy() { ... }
public T copy(){…}
编译器已经很难确定
T
类型(有时可以从赋值到的变量中确定,也可以提供
类型中缀)

但更重要的是,您不知道运行时的
t
类型,并且在方法实现中也没有任何可用的信息,无论
t
是否以某种方式绑定到
Cat
Dog
或其他什么。因此,您无法实现遵循此签名的方法


经验法则:比起类,更喜欢泛型类型参数。

感谢您的进一步澄清,我最终按照您的建议实现了类的泛型类型。在我努力理解确定泛型方法的T类型的问题之前。