有时在查看代码时,我看到许多方法都指定了注释:

@SuppressWarnings("unchecked")

这是什么意思?

有帮助吗?

解决方案

有时Java泛型只是没有让你做你想要什么,你需要有效地告诉编译器,你在做什么真正的将会的是在执行时是合法的。

我经常发现这个时,我嘲笑的通用接口痛苦,但也有其他的例子太多。它通常是值得尝试找出避免了警告,而不是抑制它( Java泛型常见问题解答<的一种方式/ A>这里帮助),但有时即使它的的可能,弯曲的代码变形,以至于抑制该警告是整洁的。总是在这种情况下添加的说明性注释!

同样的仿制药FAQ有关于这个主题几个部分,与开始“是什么一个“未登记”警告“ - ?这是很值得一读

其他提示

这是一个注释抑制编译关于选中的通用操作(未例外),如石膏的警告。它实质上意味着程序员不希望被通知关于这些,他已经知道编译代码的特定位时的感觉。

您可以阅读更多关于这个具体的注解这里:

  

SuppressWarnings

此外,Oracle提供关于注释的使用在这里的一些教程文件:

  

注解

正如他们所说的那样,

  

“可以与泛型(在题为泛型课讨论)出现之前旧代码交互时发生的未选中的警告。”

这也可能意味着当前的 Java 类型系统版本不足以满足您的情况。有几个 JSR 提议 / hacks 来解决这个问题:输入令牌, 超级类型代币, Class.cast()。

如果您确实需要这种抑制,请尽可能缩小范围(例如不要将其放在类本身或长方法上)。一个例子:

public List<String> getALegacyListReversed() {
   @SuppressWarnings("unchecked") List<String> list =
       (List<String>)legacyLibrary.getStringList();

   Collections.reverse(list);
   return list;
}

SuppressWarning 注解用于抑制的注释元素编译器警告。具体而言,unchecked类别允许作为未经检查的类型的结果而产生的编译器警告的抑制管型。

简单:它是一个警告,通过该编译器指示它不能确保类型安全

例如JPA服务方法:

@SuppressWarnings("unchecked")
public List<User> findAllUsers(){
    Query query = entitymanager.createQuery("SELECT u FROM User u");
    return (List<User>)query.getResultList();
}

如果我didn'n anotate的@SuppressWarnings(“未登记”)在这里,它会与线,在这里我想回到我的ResultList问题。

在快捷方式类型安全装置:一种程序被认为是类型安全,如果它编译没有错误和警告,并在运行时不会引起任何意外ClassCastException异常小号

我建立在 http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals html的

在Java中,泛型是由类型擦除的手段来实现。例如,下面的代码。

List<String> hello = List.of("a", "b");
String example = hello.get(0);

被编译为以下内容。

List hello = List.of("a", "b");
String example = (String) hello.get(0);

List.of被定义为。

static <E> List<E> of(E e1, E e2);

哪些后类型擦除变得

static List of(Object e1, Object e2);

在编译器不知道什么是泛型类型在运行时,因此,如果你写这样的事情。

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;

Java虚拟机并不知道泛型类型是什么在运行程序时,所以这个编译和运行,对于Java虚拟机,这是List类型(这是它可以验证的唯一一个演员,所以它验证只)。

但是,现在加入这一行。

Integer hello = actualList.get(0);

和JVM将抛出意想不到ClassCastException,如Java编译器插入隐式转换。

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer

这是unchecked警告告诉铸造可能导致程序抛出一个异常别处程序员。抑制与@SuppressWarnings("unchecked")警告告诉程序员相信代码是安全的,不会造成意外的异常编译器。

你为什么要这么做? Java类型系统是不够好,代表所有可能的类型的使用模式。有时你可能知道,铸造是安全的,但Java没有提供一种方式来这么说 - 隐藏这样的警告,@SupressWarnings("unchecked")可以使用,使程序员可以专注于真正的警告。例如,Optional.empty()返回一个单,以避免空自选的分配不存储值。

private static final Optional<?> EMPTY = new Optional<>();
public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

此铸件是安全的,如存储在一个空的可选的值不能被检索,因此不存在意外的类转换异常的风险。

您可以禁止编译器警告,告诉仿制药是你写的代码根据它是合法的。

示例:

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

一个技巧是创建延伸的通用基本接口的接口...

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}

然后就可以投之前的instanceof检查...

Object obj = context.getAttribute(FUTURES);
if (!(obj instanceof LoadFutures)) {
    String format = "Servlet context attribute \"%s\" is not of type "
            + "LoadFutures. Its type is %s.";
    String msg = String.format(format, FUTURES, obj.getClass());
    throw new RuntimeException(msg);
}
return (LoadFutures) obj;

据我所知,现在它有抑制约仿制药的警告做;仿制药是早于JDK 5 JDK版本不支持新的编程结构,所以老结构与新的混合任何可能造成一些意想不到的结果。

编译器警告关于它的程序员,但如果程序员已经知道,他们可以把那些可怕的警告关闭使用SuppressWarnings。

编译器指示它无法确保类型安全的警告。“未经检查”警告一词具有误导性。这并不意味着警告不会以任何方式受到检查。术语“未经检查”是指编译器和运行时系统没有足够的类型信息来执行确保类型安全所需的所有类型检查。从这个意义上说,某些操作是“不受控制的”。

“未经检查”警告的最常见来源是原始类型的使用。当通过原始类型变量访问对象时,会发出“未检查”警告,因为原始类型没有提供足够的类型信息来执行所有必要的类型检查。

示例(未检查的警告与原始类型结合使用):

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 (或其超类型)的集合,那么它是安全的。但编译器无法从原始类型 TreeSet 提供的类型信息中得知。因此,该呼叫可能不安全,并且会发出“未经检查”的警告。

当编译器发现目标类型是参数化类型或类型参数的强制转换时,也会报告“未检查”警告。

示例(未经检查的警告与参数化类型或类型变量的转换结合使用):

  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 返回的对象是否是 Wrapper ,而不是检查它是否是具有特定类型成员的包装器。类似地,对类型参数 T 的强制转换在运行时被强制转换为 Object 类型,并且可能完全被优化掉。由于类型擦除,运行时系统无法在运行时执行更有用的类型检查。

在某种程度上,源代码具有误导性,因为它建议执行到相应目标类型的强制转换,而实际上强制转换的动态部分仅检查目标类型的类型擦除。发出“未经检查”的警告是为了引起程序员注意强制类型转换的静态和动态方面之间的这种不匹配。

请参考: 什么是“未经检查”的警告?

@SuppressWarnings 注释是 JDK 中可用的三个内置注释之一,在 Java 1.5 中与 @Override 和 @Deprecated 一起添加。

@SuppressWarnings 指示编译器忽略或抑制带注释的元素以及该元素内的所有程序元素中指定的编译器警告。例如,如果一个类被注释为抑制特定警告,那么该类内部的方法中生成的警告也将被分离。

您可能已经见过 @SuppressWarnings("unchecked") 和 @SuppressWarnings("serial"),这是 @SuppressWarnings 注释的两个最流行的示例。前者用于抑制由于未检查的转换而生成的警告,而后者用于提醒在 Serialized 类中添加 SerialVersionUID。

阅读更多: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top