0

我有以下代码,因为我理解了<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可能不会附加泛型。

4

2 回答 2

4

这显然不是类型安全的。你可以写

ArrayBuffer a = new ArrayBuffer(0);
DynamicDrawArrayBuffer d = a.create();

这将导致ClassCastException. 该create方法的返回类型是从调用站点推断出来的。此处调用站点上唯一可用的信息是返回值必须是 a 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;
    }
}
于 2014-03-19T09:43:14.907 回答
2

更简化的版本:

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指出代码中确实缺乏类型安全性。

于 2014-03-19T09:43:36.667 回答