在通用Java中强制转换更好的解决方案 [英] better solution with cast in generic java
问题描述
Object li = new Object();
//这会导致编译器警告
ArrayList< String> lo =(ArrayList< String>)(li);
好的,我编辑了这个问题,抱歉,我犯了一个错误,关键是,因为它当我们转换到目标是一个参数化类型的目标时,会产生编译时警告,有没有更好的解决方案,以便我可以防止代码导致编译时警告?
在处理数组时,我们使用Arrays.newInstance来替换使用cast。
原始问题的代码:
// List< String>是ArrayList的超类
List< String> listOne = new List< String>();
ArrayList< String> listTwo =(List< String>)listOne;
如果您遇到这种情况,选项。首先是做一个未经检查的强制转换:
Object o = getObjectFromSomewhereMysterious();
列表< String> lst =(List< String>)o; //编译器警告
这会引起你提到的警告 - 这意味着,一个href =http://docs.oracle.com/javase/tutorial/java/generics/erasure.html =nofollow>类型擦除,
在运行时只能检查转换确保 o
是 List
,但不是 List< String>
。例如,如果 o
是 HashMap
,那么演员阵容将立即失败,但是如果它是列表< Integer>
它不会失败...直到某些以后,当您尝试将 lst
的元素视为字符串
。这被称为污染堆:
//稍后放置在代码路径中 - 谁知道,它可能在数英里之外
String str = lst.get(0); // ClassCastException如果lst不是一个真正的List< String>
只要您确定转换是安全的,就可以禁止编译器警告:
@SuppressWarnings(unchecked)//这是安全的,因为等于等于
List< String> lst =(List< String>)o;
总是记录警告可以被抑制的原因 - 这有助于保持代码可维护。
第二个选项是安全地使用它:
列表与LT;?> lst =(List<> o;
这意味着 lst
是一个 一些未知类型的列表
。它允许你避免未经检查的强制转换,但限制你可以用 lst
做什么:
lst.add(some string); //编译器错误
该语句是非法的,因为我们不知道 lst
可以容纳 String
s。我们可以做的最好的是从中读取,但即使这样,元素也只能输入为 Object
:
Object element = lst.get(0);
Suppose I have the following code:
Object li = new Object();
// this causes a compiler warning
ArrayList<String> lo = (ArrayList<String>)(li);
Okay, I have edited the question, sorry, I made a mistake, the point is, since it will cause a compile time warning when we cast to the target, whose target is a parameterized type, is there any better solution so that I can prevent the code from causing a compile time warning?
When dealing with arrays, we have Arrays.newInstance to replace the use of cast.
code from original question:
// List<String> is a superclass of ArrayList
List<String> listOne = new List<String>();
ArrayList<String> listTwo = (List<String>) listOne;
If you are in such a situation, you have two options. The first is to do an unchecked cast:
Object o = getObjectFromSomewhereMysterious();
List<String> lst = (List<String>)o; //compiler warning
This will cause the warning you mention - what it means is that, because of type erasure,
at runtime the cast can only check to make sure o
is a List
, but not a List<String>
. So for example if o
is a HashMap
the cast will fail immediately, but if it's a List<Integer>
it won't fail... until some later time when you try to treat an element of lst
like a String
. This is known as "polluting the heap":
//some later place in the code path - who knows, it could be miles away
String str = lst.get(0); //ClassCastException if lst isn't really a List<String>
As long as you can be sure that the cast is safe, you can suppress the compiler warning:
@SuppressWarnings("unchecked") //this is safe because blah blah blah
List<String> lst = (List<String>)o;
Always document why the warning can be suppressed - this helps to keep the code maintainable.
The second option is to play it safe:
List<?> lst = (List<?>)o;
This means lst
is a List
of some unknown type. It allows you to avoid the unchecked cast, but places restrictions on what you can do with lst
:
lst.add("some string"); //compiler error
That statement is illegal since we don't know whether lst
is allowed to hold String
s. The best we can do is read from it, but even then elements are only typed as Object
:
Object element = lst.get(0);
这篇关于在通用Java中强制转换更好的解决方案的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!