我有(另一个)未经检查的演员问题。我90%确定它是安全的,但我想确定(我正在使用@SupressWarnings
向另一位正在审核代码的开发人员证明)
我们的框架已经设置了以下模式:
abstract class Writer<T> {
Class<T> valueType;
Writer(Class<T> valueType) {
this.valueType = valueType;
}
}
class Cat { }
class CatWriter extends Writer<Cat> {
CatWriter() {
super(Cat.class);
}
}
我也在使用Writer
的子类来编写一个使用泛型的类:
class Color {}
class Green extends Color {}
class Brown extends Color {}
我的作家课看起来像这样:
abstract class Bird<C extends Color> {}
class Parrot extends Bird<Green>{}
class Ostrich extends Bird<Brown>{}
class BirdWriter<C extends Color> extends Writer<Bird<C>> {
BirdWriter(Bird<C> bird) {
super((Class<Bird<C>>)bird.getClass());
}
}
我可以在编写器中使用原始类型但是会提供更多警告。相反,我在Writer类中包含泛型。除了构造函数之外,这到处都很好。我被迫将bird.getClass()
(这是一个没有通用签名的类对象)强制转换为带有通用签名的Class对象。 这会在广告上产生未经检查的广告警告,但我相信将结果转换为Class<Bird<C>>
是安全的,因为传递的bird
进入参数保证是Bird<C>
。
测试支持我的理论,但我想确保我的想法是正确的。 这段代码有什么方法不安全吗?
感谢您的回答。由于答案,我意识到我的结构存在缺陷,并对其进行了修改。
基本上Cat
使用一个简单的Writer
,它知道它总是在写Cat
。在我的例子中,我有一种可以由动态Writer编写的“SmartAnimal”,因此我不必为每个Animal创建Writer
。
class SmartAnimal {}
class Dog extends SmartAnimal {}
class Horse extends SmartAnimal {}
class SuperHorse extends Horse {}
class DynamicWriter<A extends SmartAnimal> extends Writer<A> {
DynamicWriter(A smartAnimal) {
super((Class<A>)smartAnimal.getClass());
}
}
同样,我也有同样的警告,但这似乎更安全。
这样更好,是否安全?
答案 0 :(得分:4)
你并不完全正确。正确,安全但仍未经检查的演员阵容是Class<? extends Bird<C>>
,因为您传递的鸟可能是猫头鹰,它会返回Class<Owl>
,可以分配给{{1} }}。彼得劳里是正确的,因为这是不受制约但安全的。
更新
不,出于同样的原因,它仍然不安全。您仍然可以执行Class<? extends Bird<C>>
之类的操作,这会执行从new DynamicWriter<Horse>(new SuperHorse());
到Class<SuperHorse>
的未经检查的广播。为安全起见,您需要转换为Class<Horse>
。
答案 1 :(得分:3)
由于ILMTitan in his answer列出的原因,这肯定是不正确的。但我会告诉你为什么它也可能不太安全。想象一下,你有一个方法verifyType()
,确保传入的任何内容都是正确的类型:
public void write(T t) {
if (!verifyType(t)) explode();
//...do write
}
public boolean verifyType(T t) {
return valueType.isInstance(t);
}
你期望这种方法永远不会失败,对吗?毕竟,您只是确保t
是T
(因为您有Class<T>
),我们已经知道 a {{1因为T
只接受write()
?对? 错误!您实际上并未检查T
是否为t
,但可能是某个T
的任意子类型。
检查如果您声明T
并使用Writer<Bird<Green>>
对其进行实例化会发生什么情况,执行此调用将是 legal :
Parrot<Green>
再次你不会指望它会失败。但是,您的值类型仅适用于Writer<Bird<Green>> writer;
writer.write(new SomeOtherGreenBird());
,因此类型检查将失败。这一切都取决于你在作家班上所做的事情,但要预先警告:你在这里踩着危险的水。在你的作家中声明Parrot
可以防止你犯这样的错误。
答案 2 :(得分:1)
恕我直言,它是安全的。问题是getClass()在运行时返回对象的类,但是编译器不理解getClass()的作用,也没有像
Class<this> getClass();
可能是因为它是使用它的唯一例子。