2010-04-22 50 views
24

我想我会得到什么未经检查的投射手段(从一个投射到另一个不同类型),但是“检查”投射是什么意思?如何检查演员阵容,以便在Eclipse中避免此警告?什么是未经检查的演员,我如何检查它?

+1

发表我的源代码。 – 2010-04-22 17:54:31

+12

不要发布代码!不要让他们给你一条鱼,而不是教导钓鱼:)不,严肃地说,即使问题是以业余风格被问到,是否应该对通用问题有一个通用的答案。 – Mike 2014-07-15 15:25:32

回答

28

未经检查的转换意味着您(隐式或显式)从泛型类型转换为非限定类型或以其他方式转换。例如。这条线

Set<String> set = new HashSet(); 

会产生这样的警告。

通常这样的警告有很好的理由,所以你应该尝试改进你的代码而不是压制警告。来自Effective Java的报价,第二版:

消除每一个未经检查的警告,你可以。如果你消除了所有的警告,你可以放心,你的代码是类型安全的,这是一件很好的事情。这意味着您在运行时不会得到ClassCastException,并且它会增加您对程序运行的信心。

如果不能消除警告,可以证明该 引发警告的代码是类型安全的,那么(只有这样)与@SuppressWarnings("unchecked")注解抑制警告 。如果您在没有首先证明代码是类型安全的情况下取消警告 ,那么您只会给自己一个虚假的安全感。代码可以在不发出任何警告的情况下进行编译,但在运行时它仍然可以抛出ClassCastException。但是,如果您忽略 未经检查的警告(您知道这些警告是安全的(而不是禁止它们)),那么您的 将不会注意到何时出现一个代表真正问题的新警告。新的警告将在你没有沉默的所有虚假警报中消失。

当然,消除警告并不总是像上面的代码那样容易。没有看到你的代码,没有办法告诉如何使它安全。

+0

这样如何未选中铸造: 'FoodBag BAG2 =新FoodBag ();'' ((FoodBag )BAG2).setFood(新CheeseSandwich());' 从一个普通类型的泛型类型? – Datoraki 2011-04-21 14:57:39

+0

@Datoraki,你能对你的问题更具体吗? – 2011-04-21 15:10:27

+19

-1因为答案没有解决“如何检查投射”问题的一部分。好的,我们知道我们应该检查演员,**我们该怎么做? – Mike 2014-07-14 14:44:24

39

要ellaborate详细了解有关彼得写道:

从非泛型类型泛型类型强制转换可能工作在运行时间就好了,因为通用参数在编译过程中删除,因此,我们只剩下一个合法的演员。但是,由于有关类型参数的错误假设,代码可能会在以后出现意外的ClassCastException时失败。例如:

List l1 = new ArrayList(); 
l1.add(33); 
ArrayList<String> l2 = (ArrayList<String>) l1; 
String s = l2.get(0); 

未检查的警告在第3行表示该编译器不能保证类型安全了,在这个意义上,一个意想不到的ClassCastException异常可能somewere后occure。这发生在第4行,它执行隐式转换。

+5

这应该是被接受的答案 – CodyBugstein 2013-08-12 18:41:37

0

与检查强制转换相反,未经检查的强制转换不会在运行时检查类型安全性。

下面是一个基于3rd ed的Consider typesafe heterogenous containers部分的示例。“有效的Java”由Joshua布洛赫,但容器类的故意损坏 - 它保存并返回错误类型:

public class Test { 

    private static class BrokenGenericContainer{ 
     private final Map<Class<?>, Object> map= new HashMap<>(); 

     public <T> void store(Class<T> key, T value){ 
      map.put(key, "broken!"); // should've been [value] here instead of "broken!" 
     } 

     public <T> T retrieve(Class<T> key){ 
//   return key.cast(map.get(key)); // a checked cast 
      return (T)map.get(key);  // an unchecked cast 
     } 

    } 

    public static void main(String[] args) { 
     BrokenGenericContainer c= new BrokenGenericContainer(); 
     c.store(Integer.class, 42); 
     List<Integer> ints = new ArrayList<>(); 
     ints.add(c.retrieve(Integer.class)); 
     Integer i = ints.get(0); 
    } 

} 


如果retrieve()使用的选中投 - (T)map.get(key) - 运行此程序会导致ClassCastException发生在Integer i = ints.get(0)一行。该retrieve()方法完成,因为实际的类型没有在运行时检查:

Exception in thread "main" 
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer 
    at Test.main(Test.java:27) 


但如果retrieve()使用检查转换 - key.cast(map.get(key)) - 运行此程序会导致ClassCastExceptionkey.cast(map.get(key))线中发生,因为检查过的演员会发现该类型错误并抛出异常。该retrieve()方法将无法完成:

Exception in thread "main" java.lang.ClassCastException: 
              Cannot cast java.lang.String to java.lang.Integer 
    at java.lang.Class.cast(Class.java:3369) 
    at Test$BrokenGenericContainer.retrieve(Test.java:16) 
    at Test.main(Test.java:26) 

差异不大,它可能看起来,但与选中投的情况下,String成功地做了它的方式进入List<Integer>。在现实世界的应用中,这可能会导致严重的后果。在被检查的演员的情况下,尽可能早地发现类型不匹配。


为了避免未经检查的强制转换警告,@SuppressWarnings("unchecked")可以使用,如果程序员真的是肯定的方法,其实是安全的。更好的选择是在可能的情况下使用泛型和检查转换。

由于约书亚·布洛克所言,

... unchecked警告是非常重要的。不要忽视它们。


为了完整起见,this答案涉及Eclipse的细节。