java 类型安全:从对象到列表的未经检查的强制转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26976978/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:59:17  来源:igfitidea点击:

Type safety: Unchecked cast from Object to List

javagenerics

提问by spiderman

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

// some code..

// 一些代码..

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

Definition of execute()method:

execute()方法定义:

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

"Execute the stored procedure and return a map of output params, keyed by name as in parameter declarations.."

“执行存储过程并返回输出参数的映射,按参数声明中的名称键入..”

The warning on the above line : List<Student> students = (List<Student>) result.get("out_refcursor");

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

is "Type safety: Unchecked cast from Object to List"

是“类型安全:从对象到列表的未经检查的强制转换”

I understand it is only a compile time warning, and Offcourse I can do a @SuppressWarnings("unchecked")to supress it.

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

Question:But how do I properly cast it?

问题:但我如何正确施放它?

  1. One way I tried out is

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

        @SuppressWarnings("unchecked")
         private static <T extends List<?>> T castObject(Object obj){
          return (T)obj;
         }
    
  1. 我尝试过的一种方法是

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

        @SuppressWarnings("unchecked")
         private static <T extends List<?>> T castObject(Object obj){
          return (T)obj;
         }
    

Still I had to put @SuppressWarnings("unchecked")in the castObject() method. And I don't know if this is correct way of doing.

我仍然必须放入@SuppressWarnings("unchecked")castObject() 方法。我不知道这是否是正确的做法。

  1. Second way I tried is,

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

Any suggestions/advice are welcome.

欢迎任何建议/建议。

回答by ToYonos

Some thing like that could work, as long as you know the class name of the element of the List. One issue here, the hard coded ArrayListinstantiation.

只要您知道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;
}

Usage :

用法 :

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

回答by declension

Your second solution won't help (due to Type Erasure), and will cause other problems too so probably not a good idea.

您的第二个解决方案无济于事(由于Type Erasure),并且也会导致其他问题,因此可能不是一个好主意。

The first method will probably work in practice, but is a bit dodgy really. There's a subtle (but huge) difference between sub-classing Generic typesand subclassing their parametersin Java - i.e. ArrayList<Integer>is not a subclass of ArrayList<Object>, but ArrayList<String>is a sub-type of Collection<String>: see a more fun example. More formal Computer Sciencey background in Wikipedia entry on Covariance.

第一种方法在实践中可能会奏效,但确实有点狡猾。在 Java 中泛型类型进行子类化对它们的参数进行子类化之间存在细微的(但巨大的)差异- 即ArrayList<Integer>不是 的子类ArrayList<Object>,而是ArrayList<String>的子类型Collection<String>:查看更有趣的示例维基百科关于协方差的条目中有更正式的计算机科学背景。

So, IMO you should keep the casting there, keep the (necessary) annotation, and catch the ClassCastExceptionto make sure that the exceptional (hence the name) cases are covered.

因此,IMO 您应该将强制转换保留在那里,保留(必要的)注释,并捕获ClassCastException以确保涵盖特殊(因此得名)的情况。