如何"检查"演员?

时间:2015-10-16 07:55:31

标签: java generics dictionary android-studio casting

我编写了一个从Map获取随机值的方法。我首先获得了地图中的所有值,并使用Random对象来获取随机值。这是方法:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();
    V[] array = (V[])values.toArray ();
    return array[random.nextInt (array.length)];
}

在表达式

(V[])values.toArray ()

Android Studio表示,它是Object[]V[]&#34;的未经检查的演员表。所以我猜这有点冒险&#34;。我尝试使用toArray的另一个重载:

V[] array = new V[values.size()];
array = values.toArray (array);

我想这不是你如何使用重载,因为编译错误说我无法初始化V

所以我想也许我应该使用第一种方法。但是我如何检查&#34;演员取消警告?

或者,您可以告诉我如何正确使用toArray(T[] array)重载。

5 个答案:

答案 0 :(得分:2)

您无法创建泛型类型的数组,这是Java中的已知限制,并且有充分的理由。所以这是不可能的:V[] array = new V[values.size()];

另见:

What's the reason I can't create generic array types in Java?

答案 1 :(得分:1)

更好的方法是不要创建新的数组:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();

    Iterator<V> it = values.iterator();
    int choosen = new Random().nextInt (values.size());
    for (int i=0; i<values.size();i++) {
        V value = it.next();
        if (i==choosen) return value;
    }
    throw new AssertionError("Choosen value out of bounds");
}

答案 2 :(得分:0)

您可以使用instanceof在运行时检查它,但是如果您知道,只有正确类型的对象将在地图中,您应该保持原样 - 修复警告,带来不必要的运行时开销是个坏主意。此警告基本上意味着,无法确定您始终从地图中获取正确的对象。

由于类型删除new V无法正常工作。当引入泛型时,这是Java中的设计决策,以保持向后兼容性。

如果您只关心警告,当然可以禁止警告。

答案 3 :(得分:0)

Java中有type erasure,编译时将删除泛型类型,并将其作为Object类型处理。

您可以通过以下方式禁止警告:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();
    @SuppressWarnings("unchecked") V[] array = (V[])values.toArray ();
    return array[1];
}

答案 4 :(得分:0)

使用 Array.newInstance 在Thinking in Java 中引用Bruce Eckel是在泛型中创建数组的推荐方法

public class ArrayMaker<T> { 
 private Class<T> kind; 
 public ArrayMaker(Class<T> kind) { this.kind = kind; } 
 @SuppressWarnings("unchecked") 
 T[] create(int size) { 
  return (T[])Array.newInstance(kind, size); 
 }
}

您可以使用此方法,并根据地图的键和值填充数组。