[英]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.