【问题标题】:How to "check" a cast?如何“检查”演员表?
【发布时间】:2015-10-16 07:55:30
【问题描述】:

我编写了一个从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[] 的未经检查的转换”。所以我想这有点“冒险”。我尝试使用 toArray 的另一个重载:

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

我猜这不是您使用重载的方式,因为编译器错误提示我无法初始化 V

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

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

【问题讨论】:

    标签: java generics dictionary android-studio casting


    【解决方案1】:

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

    另见:

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

    【讨论】:

      【解决方案2】:

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

      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");
      }
      

      【讨论】:

      • 嗯,我喜欢你的想法。让我试试看。
      【解决方案3】:

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

      new V类型擦除而无法工作。这是 Java 在引入泛型时为了保持向后兼容性而做出的设计决定。

      如果你只关心警告,当然可以压制它。

      【讨论】:

        【解决方案4】:

        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];
        }
        

        【讨论】:

          【解决方案5】:

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

          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); 
           }
          }
          

          您可以使用这种方法并根据 Map 的键和值填充数组。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-02-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-06-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多