[英]Avoiding unchecked casts with generics with double extending classes?
我有以下代码,由于我理解了<T extends Buffer>
真正含义,因此我将其重构为以下代码:
public class Buffer {
protected final int bufferType;
protected final int bufferDataType;
protected int bufferId;
protected boolean created;
public Buffer(final int bufferType, final int bufferDataType) {
this.bufferType = bufferType;
this.bufferDataType = bufferDataType;
}
public <T extends Buffer> T create() {
assertNotCreated();
bufferId = GL15.glGenBuffers();
created = true;
return (T)this;
}
public boolean hasBeenCreated() {
return created;
}
private void assertNotCreated() {
if (hasBeenCreated()) {
throw new RuntimeException("Buffer has been created already.");
}
}
}
public class ArrayBuffer extends Buffer {
public ArrayBuffer(final int bufferDataType) {
super(GL15.GL_ARRAY_BUFFER, bufferDataType);
}
}
public class DynamicDrawArrayBuffer extends ArrayBuffer {
public DynamicDrawArrayBuffer() {
super(GL15.GL_DYNAMIC_DRAW);
}
}
该警告发生在Buffer.create()
,抑制警告是否安全? 有什么方法可以使其更安全?
另一个要求是,不应在此API的调用/使用代码中添加任何混乱, DynamicDrawArrayBuffer
,这意味着DynamicDrawArrayBuffer
可能不会附加泛型。
这显然不是类型安全的。 你可以写
ArrayBuffer a = new ArrayBuffer(0);
DynamicDrawArrayBuffer d = a.create();
这将导致ClassCastException
。 从调用站点推断出create
方法的返回类型。 在此,呼叫站点上唯一可用的信息是返回值必须是DynamicDrawArrayBuffer
因此ArrayBuffer
被强制转换为1。
我认为您可以在此处轻松利用协方差: create
方法始终可以返回类的类型。 然后, create
方法的返回类型取决于调用该方法时所具有的类型信息:
public class BufferTest
{
public static void main(String[] args)
{
ArrayBuffer a = new ArrayBuffer();
ArrayBuffer aa = a.create(); // Yes
// DynamicDrawArrayBuffer ad = a.create(); // No
DynamicDrawArrayBuffer d = new DynamicDrawArrayBuffer();
ArrayBuffer da = a.create(); // Yes
DynamicDrawArrayBuffer dd = d.create(); // Yes
Buffer b = a;
Buffer bb = b.create(); // Yes
//ArrayBuffer ba = b.create(); // No
}
}
class Buffer
{
public Buffer create()
{
// create etc...
return this;
}
}
class DynamicDrawArrayBuffer extends ArrayBuffer
{
@Override
public DynamicDrawArrayBuffer create()
{
super.create();
return this;
}
}
class ArrayBuffer extends Buffer
{
@Override
public ArrayBuffer create()
{
super.create();
return this;
}
}
更简化的版本:
public class Buffer {
public <T extends Buffer> T create() {
return (T)this;
}
public static class FooBuffer extends Buffer {}
public static class BarBuffer extends FooBuffer {}
public static void main(String... args) {
BarBuffer b = new FooBuffer().create();
}
}
main
方法在没有警告的情况下进行编译,运行代码将导致ClassCastException
。 create
的警告指出代码中确实缺乏类型安全性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.