有时在查看代码时,我看到许多方法都指定了注释:
@SuppressWarnings("unchecked")
这是什么意思?
有时在查看代码时,我看到许多方法都指定了注释:
@SuppressWarnings("unchecked")
这是什么意思?
当前回答
简单地说:这是一个警告,编译器通过它表示它不能确保类型安全。
例如,JPA服务方法:
@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
Query query = entitymanager.createQuery("SELECT u FROM User u");
return (List<User>)query.getResultList();
}
如果我没有注释@SuppressWarnings(“unchecked”)在这里,它将有一个问题与行,我想返回我的ResultList。
简单地说,类型安全的意思是:如果一个程序在编译时没有错误和警告,并且在运行时没有引发任何意外的ClassCastException,则该程序被认为是类型安全的。
我建立在http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html上
其他回答
一种警告,编译器借此表示它不能确保类型安全。 “未经检查”的警告一词具有误导性。这并不意味着警告在任何方面都是不受限制的。术语“未检查”指的是编译器和运行时系统没有足够的类型信息来执行确保类型安全所需的所有类型检查。从这个意义上说,某些操作是“未检查”的。
“未检查”警告最常见的来源是使用原始类型。当通过原始类型变量访问对象时,会发出“unchecked”警告,因为原始类型没有提供足够的类型信息来执行所有必要的类型检查。
示例(未经检查的警告与原始类型结合):
TreeSet set = new TreeSet();
set.add("abc"); // unchecked warning
set.remove("abc");
warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.TreeSet
set.add("abc");
^
当调用add方法时,编译器不知道向集合中添加String对象是否安全。如果TreeSet是一个包含String s(或其超类型)的集合,那么它是安全的。但是从原始类型TreeSet提供的类型信息,编译器无法判断。因此,该呼叫可能是不安全的,并发出“未检查”警告。
当编译器发现目标类型为参数化类型或类型形参的强制转换时,还会报告"unchecked"警告。
示例(未检查的警告与参数化类型或类型变量的强制转换结合在一起):
class Wrapper<T> {
private T wrapped ;
public Wrapper (T arg) {wrapped = arg;}
...
public Wrapper <T> clone() {
Wrapper<T> clon = null;
try {
clon = (Wrapper<T>) super.clone(); // unchecked warning
} catch (CloneNotSupportedException e) {
throw new InternalError();
}
try {
Class<?> clzz = this.wrapped.getClass();
Method meth = clzz.getMethod("clone", new Class[0]);
Object dupl = meth.invoke(this.wrapped, new Object[0]);
clon.wrapped = (T) dupl; // unchecked warning
} catch (Exception e) {}
return clon;
}
}
warning: [unchecked] unchecked cast
found : java.lang.Object
required: Wrapper <T>
clon = ( Wrapper <T>)super.clone();
^
warning: [unchecked] unchecked cast
found : java.lang.Object
required: T
clon. wrapped = (T)dupl;
如果涉及到运行时的动态类型检查,则目标类型为(具体或有界通配符)参数化类型或类型参数的强制转换是不安全的。在运行时,只有类型擦除是可用的,而不是源代码中可见的确切静态类型。因此,强制转换的运行时部分是基于类型擦除执行的,而不是基于确切的静态类型。
在本例中,强制转换为Wrapper将检查对象是否从super返回。clone是一个包装器,而不是它是否是具有特定类型成员的包装器。类似地,类型参数T的类型转换在运行时被转换为Object类型,并且可能完全优化了。由于类型擦除,运行时系统无法在运行时执行更有用的类型检查。
在某种程度上,源代码具有误导性,因为它建议执行到相应目标类型的强制转换,而实际上强制转换的动态部分只检查目标类型的类型擦除。发出“unchecked”警告是为了提请程序员注意强制转换的静态和动态方面之间的不匹配。
请参考:什么是“未检查”警告?
你可以取消编译器的警告,并告诉泛型你所写的代码是合法的。
例子:
@SuppressWarnings("unchecked")
public List<ReservationMealPlan> retreiveMealPlan() {
List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>();
TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance);
list = testMenuService.getMeal(reservationMealPlan);
return list;
}
简单地说:这是一个警告,编译器通过它表示它不能确保类型安全。
例如,JPA服务方法:
@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
Query query = entitymanager.createQuery("SELECT u FROM User u");
return (List<User>)query.getResultList();
}
如果我没有注释@SuppressWarnings(“unchecked”)在这里,它将有一个问题与行,我想返回我的ResultList。
简单地说,类型安全的意思是:如果一个程序在编译时没有错误和警告,并且在运行时没有引发任何意外的ClassCastException,则该程序被认为是类型安全的。
我建立在http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html上
这也可能意味着当前的Java类型系统版本不适合您的情况。有几个JSR命题/ hack可以解决这个问题:类型令牌、超级类型令牌、Class.cast()。
如果你真的需要这个抑制,尽可能缩小它的范围(例如,不要把它放在类本身或一个长方法上)。一个例子:
public List<String> getALegacyListReversed() {
@SuppressWarnings("unchecked") List<String> list =
(List<String>)legacyLibrary.getStringList();
Collections.reverse(list);
return list;
}
据我所知,目前它与抑制关于泛型的警告有关;泛型是一种新的编程结构,在JDK 5之前的版本中不支持,因此任何新旧结构的混合都可能导致一些意想不到的结果。
编译器会警告程序员,但是如果程序员已经知道了,他们可以使用SuppressWarnings关闭这些可怕的警告。