代码之家  ›  专栏  ›  技术社区  ›  topchef

此代码中是否有避免@suppresswarnings的方法?

  •  3
  • topchef  · 技术社区  · 15 年前

    有没有办法避免使用 @SuppressWarnings 并在没有警告的情况下保持相同的功能 '类型安全:从abstractdo[]到e[]的未选中强制转换' :

    public MyClass {
      ...
      private Map<Class<? extends AbstractDO>, AbstractDO[]> map;
      ...
      private void saveConcreteDOs(AbstractDO[] theEntities) {        
        entityMap.put(theEntities[0].getClass(), theEntities);
      }
    
      @SuppressWarnings("unchecked")
      protected <E extends AbstractDO> E[] getConcreteDOs(Class<E> theType) {
        return (E[]) map.get(theType);
      }
      ...
    }
    

    可能增强地图声明?

    3 回复  |  直到 15 年前
        1
  •  3
  •   Randolpho    15 年前

    您可以选择:对已知将始终成功的强制转换取消警告,或者避免警告,并通过try/catch块验证强制转换是否成功。

    只有这两种选择。

    也许有办法加强地图申报?

    在你的情况下,我想说你有几个选择。

    我想你最好的办法是加一个 throws ClassCastException 条款 getConcreteDOs 方法,并让调用者处理方法的无效使用带来的无效强制转换——假设他们可以让它围绕 extends AbstractDO 条款。这有一个不幸的副作用,即强制使用者将调用包装在一个try/catch块中,或者声明自己的throws子句以强制将一个try/catch块放在堆栈的更高位置。

    你可以用一个空的catch块来吞下这个异常;坦率地说,我更喜欢@suppresswarning。

    或者您可以完全放弃该方法,只处理抽象实体,从而有效地使存储库的使用者处理强制转换。

    底线:每当您试图构建通用存储库时,都会遇到这些问题。对于每个实体类型模式,使用一个具体的存储库可能会更好。

        2
  •  1
  •   Péter Török    15 年前

    您可以通过使类成为泛型来避免未选中的强制转换,例如

    public class MyClass<E extends AbstractDO> {
    
        private Map<Class<? extends AbstractDO>, E[]> map;
    
        public void saveConcreteDOs(E[] theEntities) {        
          map.put(theEntities[0].getClass(), theEntities);
        }
    
        public E[] getConcreteDOs(Class<E> theType) {
          return map.get(theType);
        }
    }
    
        3
  •  1
  •   irreputable    15 年前

    首先,您的代码不是类型安全的。它可以在运行时引发类强制转换异常。你应该有

      private void saveConcreteDOs(AbstractDO[] theEntities) {        
        entityMap.put(theEntities.getClass().getComponentType(), theEntities);
      }
    

    运行时只能有同构数组,元素[0]的类型与数组组件类型相同。然而,单凭这门课的考试是不可能知道这一点的。

    有了这个修正后的代码,超级智能编译器就可以证明 getConcreteDOs() 类型安全。然而,javac并不是那么聪明。语言规范要求抛出警告。

    一般来说,没有办法在Java中表达更复杂的键和值之间的关系。不变量,即一个值是一个组件类型为键的数组,只在您的头中维护。

    现在,看看这个非数组版本:

    private Map<Class<? extends AbstractDO>, AbstractDO> map;
    
    protected <E extends AbstractDO> E getConcreteDOs(Class<E> theType) 
    {
      AbstractDO obj = map.get(theType);
      return theType.cast(obj);
    }
    

    这没有警告,但有点作弊。 Class.cast() 为我们隐藏警告,仅此而已。

    它对数组版本没有帮助,没有 T[] castArray(Object[]) 在里面 Class<T> . 您可以自己创建一个方法,有效地将警告隐藏在其中。

    或者你可以这样做,但这确实是不必要的俗气。如果您知道自己在做什么,并且仔细检查了程序以确保类型安全,那么不要害怕未选中的强制转换警告。

    protected <E extends AbstractDO> E[] getConcreteDOs(Class<E[]> arrayType) 
    {
      AbstractDO[] array = map.get(arrayType.getComponentType());
      return arrayType.cast(array);
    }
    ...
    X[] array = getConcreteDOs(X[].class);