类型安全:取消选中从对象到列表的强制转换

时间:2014-11-17 16:16:17

标签: java generics

SqlOutParameter out = new SqlOutParameter("out_refcursor",OracleTypes.CURSOR,new StudentRowMapper());

//一些代码..

MapSqlParameterSource parameters = createMapSqlParameterSource();
parameters.addValue("in_studentid","101"); 

Map<String, Object> result = simpleJdbcCall.execute(parameters);
List<Student> students = (List<Student>) result.get("out_refcursor"); // here I get a warning

execute()方法的定义:

Map<String, Object> org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SqlParameterSource parameterSource)

&#34;执行存储过程并返回输出参数的映射,按名称键入,如参数声明中所示。&#34;

以上行警告:List<Student> students = (List<Student>) result.get("out_refcursor");

是&#34;类型安全:未选中从对象转换为列表&#34;

我知道这只是一个编译时警告,而且我可以做一个@SuppressWarnings("unchecked")来压制它。

问题:但我该如何正确施展呢?

  1. 我试过的一种方法是

    List<Student> students = castObject( result.get("out_refcursor"));

        @SuppressWarnings("unchecked")
         private static <T extends List<?>> T castObject(Object obj){
          return (T)obj;
         }
    
  2. 仍然我必须将@SuppressWarnings("unchecked")放在castObject()方法中。而且我不知道这是否是正确的做法。

    1. 我试过的第二种方式是,

      List<?> students = castObject( result.get("out_refcursor"));

      Student student = (Student)students.get(0);
      
      private static <T extends List<?>> List<?> castObject(Object obj){
              if(obj instanceof List<?>) {
                  return (List<Student>)obj;
              }
              return null;
      }
      
    2. 欢迎任何建议/意见。

2 个答案:

答案 0 :(得分:5)

只要您知道List元素的类名,就可以使用这样的东西。这里有一个问题,硬编码ArrayList实例化。

public static <T> List<T> castList(Object obj, Class<T> clazz)
{
    List<T> result = new ArrayList<T>();
    if(obj instanceof List<?>)
    {
        for (Object o : (List<?>) obj)
        {
            result.add(clazz.cast(o));
        }
        return result;
    }
    return null;
}

用法:

List<Student> students = castList(result.get("out_refcursor"), Student.class);

答案 1 :(得分:4)

你的第二个解决方案无济于事(由于Type Erasure),并且会引起其他问题,所以可能不是一个好主意。

第一种方法可能会在实践中起作用,但实际上有点狡猾。 子类化通用类型在Java中对它们的参数进行子类化之间存在微妙(但巨大)差异 - 即ArrayList<Integer>不是ArrayList<Object>的子类},但ArrayList<String>Collection<String>的子类型:请参阅a more fun exampleWikipedia entry on Covariance中更正式的计算机科学背景。

所以,IMO你应该保持那里的转换,保留(必要的)注释,并抓住ClassCastException以确保覆盖异常(因此名称)案例。