避免涉及类的运行时传递的一般情况的不安全转换

发布于 2024-10-09 14:20:06 字数 932 浏览 2 评论 0原文

public class AutoKeyMap<K,V> {

    public interface KeyGenerator<K> {
        public K generate();
    }    
    private KeyGenerator<K> generator;

    public AutoKeyMap(Class<K> keyType) {
        // WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
        if (keyType == Integer.class) generator = (KeyGenerator<K>) new IntKeyGen();
        else throw new RuntimeException("Cannot generate keys for " + keyType);
    }

    public void put(V value) {
        K key = generator.generate();
        ...
    }


    private static class IntKeyGen implements KeyGenerator<Integer> {

        private final AtomicInteger ai = new AtomicInteger(1);

        @Override public Integer generate() {
            return ai.getAndIncrement();
        }

    }


}

在上面的代码示例中,在不添加 @SuppressWarnings(如果有)的情况下,防止给定警告的正确方法是什么?

public class AutoKeyMap<K,V> {

    public interface KeyGenerator<K> {
        public K generate();
    }    
    private KeyGenerator<K> generator;

    public AutoKeyMap(Class<K> keyType) {
        // WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
        if (keyType == Integer.class) generator = (KeyGenerator<K>) new IntKeyGen();
        else throw new RuntimeException("Cannot generate keys for " + keyType);
    }

    public void put(V value) {
        K key = generator.generate();
        ...
    }


    private static class IntKeyGen implements KeyGenerator<Integer> {

        private final AtomicInteger ai = new AtomicInteger(1);

        @Override public Integer generate() {
            return ai.getAndIncrement();
        }

    }


}

In the code sample above, what is the correct way to prevent the given warning, without adding a @SuppressWarnings, if any?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

老娘不死你永远是小三 2024-10-16 14:20:06

您可以通过执行以下操作暂时修复代码:

private KeyGenerator<?> generator;

public AutoKeyMap(Class<?> keyType) {
    // WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
    if (keyType == Integer.class) generator = new IntKeyGen();
    else throw new RuntimeException("Cannot generate keys for " + keyType);
}

但是如果您需要在 AutoKeyMap 中实现类似的方法

K generate(){
  return generator.generate();
}

,那么它将再次中断。问题是,一旦开始对类类型进行运行时检查(就像在 if(keyType == Integer.class) 中所做的那样),Java 编译器就无法静态地确保类型正确。因为您可以实例化 new AutoKeyMap(ClasskeyType) 然后编写

if(keyType == Boolean.class){
  generator = new IntKeyGen();
}

这显然会破坏,因此静态检查泛型类型的全部意义将会丢失。

通常,像您这样涉及动态类型转换的所有问题都超出了泛型范围,因此您必须忍受未经检查的转换,并且只需确保编写足够的单元测试并确保您的代码可以正常工作并且不会抛出 ClassCastException在所有场景中。

You can fix your code temporarily by doing this:

private KeyGenerator<?> generator;

public AutoKeyMap(Class<?> keyType) {
    // WARNING: Unchecked cast from AutoKeyMap.IntKeyGen to AutoKeyMap.KeyGenerator<K>
    if (keyType == Integer.class) generator = new IntKeyGen();
    else throw new RuntimeException("Cannot generate keys for " + keyType);
}

But if you need to implement a method in AutoKeyMap like

K generate(){
  return generator.generate();
}

then it will break again. The problem is as soon as you start doing runtime checking of class types (like you do in if(keyType == Integer.class)) then Java compiler has no way of statically ensuring that type will be correct. Because you can instantiate new AutoKeyMap<Boolean>(Class<Boolean> keyType) and then write

if(keyType == Boolean.class){
  generator = new IntKeyGen();
}

which will obviously break, and therefore the whole point of statically checked generic types will be lost.

Usually all problems like yours that involve dynamic type casting are beyond generics, so you have to live with unchecked casts, and just make sure you write enough unit tests and make sure your code works and does not throw ClassCastException in all scenarios.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文