java - 抽象类和泛型中“this”关键字的行为
问题描述
考虑以下类
就序列化而言,重新发明轮子,我知道:
abstract class AnimalSerializer<E extends Animal> {
/**
* The type E (which extends Animal) is important here.
* I want to be able to write data that is specific to a subclass of an animal.
*/
abstract void writeAnimal(E animal);
abstract Animal readAnimal();
}
abstract class Animal {
AnimalSerializer<? extends Animal> serializer;
Animal(AnimalSerializer<? extends Animal> speciesSerializer) {
serializer = speciesSerializer;
}
void writeAnimalToFile() {
// This line fails to compile
serializer.writeAnimal(this);
}
}
这些类演示了这种模式的使用:
class DogSerializer extends AnimalSerializer<Dog> {
@Override
void writeAnimal(Dog animal) {
// Write the stuff that is specific to the dog
// ...
}
@Override
Animal readAnimal() {
// Read the stuff specific to the dog, instantiate it, and cast it as an animal.
// ...
return null;
}
}
class Dog extends Animal {
String dogTag = "Data specific to dog.";
Dog() {
super(new DogSerializer());
}
}
我的问题与编译失败的行有关(serializer.writeAnimal(this)
)。我不得不第一次查阅语言规范以了解更多关于this
关键字的信息,但我认为问题在于“this”关键字属于 type Animal
,而有界通配符泛型<? extends Animal>
仅支持作为 Animal 子类的类型,不是Animal
类型本身。
我认为编译器应该知道this
关键字的类型必须是扩展 Animal 的对象,因为 Animal 不能被实例化,并且this
关键字仅适用于已经存在的对象。
编译器是否有理由不知道这一点?我的猜测是,有一个案例可以解释为什么this
不能保证关键字是 Animal 的子类。
此外,这种模式是否存在根本缺陷?
解决方案
您的serializer
通用类型是? extends Animal
. 你的this
类型是Animal
,也可以认为是? extends Animal
。但这两种?
是不同的类型。没有约束让编译器知道它们是相同的类型。
比如我写了一个Cat
类
class Cat extends Animal {
Cat(){
super(new DogSerializer()); // this is ok for your generic
}
}
这就是编译器给你一个错误的原因。
推荐阅读
- windows-10 - 由于 vagrant 和 Windows 10 的符号链接问题,无法运行 npm install
- c++ - 在 C++ 中,为什么为函数定义和声明声明不同的返回类型会改变函数的输出?
- postgresql - 退出在 PostgreSQL 中返回 JSON 的函数时删除临时表
- ruby-on-rails - 全新的 Rails 6.1.4.1 因 webpack 错误而失败 - TypeError: Class constructor ServeCommand cannot be invoked without 'new'
- java - TOMEEE - 无法查找 ejb
- python - 请帮助解释在范围函数中使用 len 函数的循环
- cypress - 赛普拉斯拦截 - 从未发生过请求
- azure - 使用 Java 从 Azure Function 访问 Key Vault 证书
- typescript - 即使使用默认参数值,对象也可能为 null
- .net - .Net 5 Azure 功能未显示在门户中