关于java:Generics中的类型安全性

Type safety in Generics

我有下面的类层次结构,它们只是实现了从给定的字节射线对动物进行编码和解码的想象功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public abstract class Animal {
}

class Tiger extends Animal{
    private String name;

    public void setName() {
    }

    public String getName() {
        return this.name;
    }
}

abstract class AnimalTransformer {
    public static <T> T decodeAnimalFromBytes(byte[] animalInBytes) {
        return null;
    }

    public static byte[] encodeAnimalInBytes(Animal animal) {
        return null;
    }

}

1
2
3
4
5
6
7
8
9
class TigerTransformer extends AnimalTransformer{
    public static Tiger decodeAnimalFromBytes(byte[] animalInBytes) {
        return new Tiger();
    }

    public static byte[] encodeAnimalinBytes(Tiger tiger) {
        return new byte[0];
    }
}

在TigerTransformer类中的AnimalTransformer抽象类重写方法时,扩展了AnimalTransformer,得到以下警告

1
2
3
Type safety: The return type Tiger for decodeAnimalFromBytes(byte[]) from the type
TigerTransformer needs unchecked conversion to conform to T
from the type AnimalTransformer

我理解这个警告的原因,但不幸的是,我不能解决它,因为我是新来的仿制药。有人能简单地解释一下如何补救这个警告吗?


请注意,使动物转化器的方法静态化是没有用的。静态方法不会通过继承相互重写。此外,您没有将转换器工作的数据类型绑定到解码对象的类型(例如,TigerTransformer可以返回horse对象)。

我将改为执行以下操作,我认为这更安全:

1
2
3
4
5
abstract class AnimalTransformer <T> {
    public abstract T decodeAnimalFromBytes(byte[] animalInBytes);

    public abstract byte[] encodeAnimalInBytes(T animal);
}

首先,不要试图用静态方法"重写"。它的工作方式与您想象的不一样-"被重写"的静态方法仍然可以通过迂回(意外)的方式从子类访问。如果要重写行为,请使用本地方法。

产生警告的原因是Tiger方法签名与超级类方法所承诺的不兼容,即客户端选择的任何类都可以解码,这是一个非常大的、无法实现的承诺。

更好的方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
abstract class AnimalTransformer<T extends Animal> {
  public T decodeAnimalFromBytes(byte[] animalInBytes) {
    return null;
  }
  public static byte[] encodeAnimalInBytes(T animal) {
    return null;
  }
}

class TigerTransformer extends AnimalTransformer<Tiger> {
  public Tiger decodeAnimalFromBytes(byte[] animalInBytes) {
    return new Tiger();
  }
  public byte[] encodeAnimalinBytes(Tiger tiger) {
      return new byte[0];
  }
}

这代表了您试图更清晰地建模的内容——一个AnimalTransformerAnimal的某些子类提供了转换方法,并且由子类或匿名实现来澄清哪一个。