我编写了一个从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)
重载。
答案 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);
}
}
您可以使用此方法,并根据地图的键和值填充数组。