【问题标题】:Unchecked cast of generic typed method return in JavaJava中泛型类型方法返回的未经检查的转换
【发布时间】:2015-11-19 09:28:17
【问题描述】:

提前道歉,我正在为如何措辞问题标题而苦苦挣扎,我知道这并不理想。

所以我尝试实现我自己的 Java HashMap 小版本,当然我希望它适用于泛型,以允许它与任何类一起使用,就像真正的 HashMap 一样。

在我的get(...) 方法中,我传递了一个键并想要返回一个值。一切正常,直到我尝试返回某些东西,然后我收到常见的Xlint:unchecked 类型安全警告,即无法验证我的返回值类型。看下面的sn-p:

public <K, V> V get (K key) {
    if(!(key instanceof Object)) {
        System.out.println("ERROR: key given can't be guaranteed to have a hash function");
        return null;
    }
    int hashCode = key.hashCode();
    int index = hashCode % items.length;

    HashItem slot = items[index];
    while(slot != null) {
        if(slot.getKey().equals(key)) {
            V val = slot.getVal();
            return val;
        }
        slot = slot.getNext();
    }
    return null;
}

参考见.getVal()的定义:

public V getVal() {
    return HashItem.this.val;
}

.getVal() 方法是私有内部类HashItem&lt;K, V&gt; 的一部分:

private class HashItem <K, V> {
    // blah blah
}

自制的哈希映射类本身的结构如下:

public class MyHash <K, V>
{
    // blah blah

    private class HashItem <K, V> {
    // blah blah

        public V getVal() {
            return HashItem.this.val;
        }

        // blah blah
    }

    public MyHash (int capacity, double newLoadFactor) {
        // blah blah
    }

    // blah blah etc etc
}

由于KV 始终保持不变,我不明白为什么不能保证.getVal() 的类型,或者如何解决这个问题。我尝试像这样进行转换:(V) 可以工作,但返回 unchecked cast 错误。我也尝试只返回值,但我只得到返回类型Object,这是不可接受的。

如何让我的.getVal() 方法返回正确的类型?

【问题讨论】:

  • get 不应该是通用方法。类应该是通用的,而不是方法,所以 public &lt;K, V&gt; V get (K key) 中的 &lt;K, V&gt; 不应该存在。
  • 我没有专门看这段代码,但是很多基于集合的类——尤其是那些使用数组的类,就像哈希映射一样——由于类型而存在未经检查的警告异常擦除。警告并不意味着您做错了什么,只是类型系统无法帮助您;您应该确保它是正确的,然后使用@SuppressWarnings("unchecked") 抑制警告。单独说明:Java 中每个类都是 Object 的子类,所以不用勾选instanceof Object
  • HashItem 也不应该有类型参数&lt;K, V&gt;,它应该只使用来自MyHash 的参数。
  • 另请注意,在真正的HashMap 中,get 接受Object,而不是K。起初这似乎是错误的,但这样做真的很重要。如果getcontainsKey 接受K 而不是Object,则无法检查Map&lt;? extends CharSequence, Object&gt; 是否包含密钥"Foo",因为您无法将String 传递给getcontainsKey 方法。 put,另一方面应该接受 KV

标签: java generics


【解决方案1】:

1.将public &lt;K, V&gt; V get(K key)改为public V get(K key)

2.将HashItem slot = items[index];改为HashItem&lt;K, V&gt; slot = items[index];

示例代码:

public class MyHash<K, V> {
    // blah blah

    private class HashItem<K, V> {
        // blah blah
        V val;
        K key;

        public V getVal() {
            return HashItem.this.val;
        }

        public K getKey() {
            return HashItem.this.key;
        }

        public HashItem<K, V> getNext() {
            return null;
        }

        // blah blah
    }

    HashItem<K, V>[] items;

    public V get(K key) {
        if (!(key instanceof Object)) {
            System.out.println("ERROR: key given can't be guaranteed to have a hash function");
            return null;
        }
        int hashCode = key.hashCode();
        int index = hashCode % items.length;

        HashItem<K, V> slot = items[index];
        while (slot != null) {
            if (slot.getKey().equals(key)) {
                V val = slot.getVal();
                return val;
            }
            slot = slot.getNext();
        }
        return null;
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-13
    相关资源
    最近更新 更多