繁体   English   中英

避免使用具有双扩展类的泛型进行未经检查的强制转换?

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM