Java 中的 SuppressWarnings(“未选中”)是什么?

发布于 2024-07-26 22:57:42 字数 103 浏览 7 评论 0原文

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

@SuppressWarnings("unchecked")

这是什么意思?

Sometime when looking through code, I see many methods specify an annotation:

@SuppressWarnings("unchecked")

What does this mean?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

蓦然回首 2024-08-02 22:57:42

有时,Java 泛型不允许您做您想做的事情,您需要有效地告诉编译器您所做的事情在执行时确实是合法的。

当我嘲笑通用接口时,我通常会觉得这很痛苦,但也有其他例子。 通常值得尝试找出一种方法来避免警告而不是抑制警告(Java 泛型常见问题< /a> 在这里有所帮助),但有时即使它可能的,它也会使代码变形得太多,以至于抑制警告会更简洁。 在这种情况下,请务必添加解释性注释!

相同的仿制药常见问题解答有几个关于此主题的部分,从 “什么是“未检查”开始“警告?” - 非常值得一读。

Sometimes Java generics just doesn't let you do what you want to, and you need to effectively tell the compiler that what you're doing really will be legal at execution time.

I usually find this a pain when I'm mocking a generic interface, but there are other examples too. It's usually worth trying to work out a way of avoiding the warning rather than suppressing it (the Java Generics FAQ helps here) but sometimes even if it is possible, it bends the code out of shape so much that suppressing the warning is neater. Always add an explanatory comment in that case!

The same generics FAQ has several sections on this topic, starting with "What is an "unchecked" warning?" - it's well worth a read.

初心 2024-08-02 22:57:42

它是一个注释,用于抑制有关未经检查的泛型操作(不是例外)的编译警告,例如强制转换。 它本质上意味着程序员不希望收到有关他在编译特定代码时已经知道的这些信息的通知。

您可以在此处阅读有关此特定注释的更多信息:

SuppressWarnings

此外,Oracle 还提供了一些关于这里使用注解:

注释

正如他们所说,

“与泛型出现之前编写的遗留代码交互时,可能会出现‘未经检查’的警告(在标题为泛型的课程中讨论)。”

It is an annotation to suppress compile warnings about unchecked generic operations (not exceptions), such as casts. It essentially implies that the programmer did not wish to be notified about these which he is already aware of when compiling a particular bit of code.

You can read more on this specific annotation here:

SuppressWarnings

Additionally, Oracle provides some tutorial documentation on the usage of annotations here:

Annotations

As they put it,

"The 'unchecked' warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled Generics)."

苏璃陌 2024-08-02 22:57:42

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

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

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

   Collections.reverse(list);
   return list;
}

It could also mean that the current Java type system version isn't good enough for your case. There were several JSR propositions / hacks to fix this: Type tokens, Super Type Tokens, Class.cast().

If you really need this supression, narrow it down as much as possible (e.g. don't put it onto the class itself or onto a long method). An example:

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

   Collections.reverse(list);
   return list;
}
陌上青苔 2024-08-02 22:57:42

简单地说:这是一个警告,编译器表明它无法确保类型安全。

例如,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< /a>

Simply: It's a warning by which the compiler indicates that it cannot ensure type safety.

JPA service method for example:

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

If I didn'n anotate the @SuppressWarnings("unchecked") here, it would have a problem with line, where I want to return my ResultList.

In shortcut type-safety means: A program is considered type-safe if it compiles without errors and warnings and does not raise any unexpected ClassCastException s at runtime.

I build on http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html

倾城花音 2024-08-02 22:57:42

在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);

当 Java 编译器插入隐式转换时,JVM 将抛出意外的 ClassCastException

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

这种转换是安全的,因为无法检索存储在空可选值中的值,因此不存在意外类转换异常的风险。

In Java, generics are implemented by means of type erasure. For instance, the following code.

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

Is compiled to the following.

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

And List.of is defined as.

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

Which after type erasure becomes.

static List of(Object e1, Object e2);

The compiler has no idea what are generic types at runtime, so if you write something like this.

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

Java Virtual Machine has no idea what generic types are while running a program, so this compiles and runs, as for Java Virtual Machine, this is a cast to List type (this is the only thing it can verify, so it verifies only that).

But now add this line.

Integer hello = actualList.get(0);

And JVM will throw an unexpected ClassCastException, as Java compiler inserted an implicit cast.

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

An unchecked warning tells a programmer that a cast may cause a program to throw an exception somewhere else. Suppressing the warning with @SuppressWarnings("unchecked") tells the compiler that the programmer believes the code to be safe and won't cause unexpected exceptions.

Why would you want to do that? Java type system isn't good enough to represent all possible type usage patterns. Sometimes you may know that a cast is safe, but Java doesn't provide a way to say so - to hide warnings like this, @SupressWarnings("unchecked") can be used, so that a programmer can focus on real warnings. For instance, Optional.empty() returns a singleton to avoid allocation of empty optionals that don't store a value.

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

This cast is safe, as the value stored in an empty optional cannot be retrieved so there is no risk of unexpected class cast exceptions.

风和你 2024-08-02 22:57:42

SuppressWarning 注释用于禁止对带注释的元素发出编译器警告。 具体来说,unchecked 类别允许抑制由于未经检查的类型转换而生成的编译器警告。

The SuppressWarning annotation is used to suppress compiler warnings for the annotated element. Specifically, the unchecked category allows suppression of compiler warnings generated as a result of unchecked type casts.

好久不见√ 2024-08-02 22:57:42

您可以抑制编译器警告并告诉泛型您编写的代码根据它是合法的。

例子:

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

You can suppress the compiler warnings and tell the generics that the code which you had written is legal according to it.

Example:

@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;
 }
予囚 2024-08-02 22:57:42

一个技巧是创建一个扩展通用基接口的接口...

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;

One trick is to create an interface that extends a generic base interface...

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

Then you can check it with instanceof before the cast...

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;
风启觞 2024-08-02 22:57:42

据我所知,目前它与抑制有关泛型的警告有关; 泛型是一种新的编程结构,早于 JDK 5 的 JDK 版本不支持,因此旧结构与新结构的任何混合都可能会产生一些意想不到的结果。

编译器会向程序员发出警告,但如果程序员已经知道,他们可以使用 SuppressWarnings 关闭这些可怕的警告。

As far I know, for now it has to do with suppressing warnings about generics; generics are a new programming construct not supported in JDK versions earlier than JDK 5, so any mixes of the old constructs with the new ones might pose some unexpected results.

The compiler warns the programmer about it, but if the programmer already knows, they can turn those dreaded warnings off using SuppressWarnings.

客…行舟 2024-08-02 22:57:42

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

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

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

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 类型,并且可能完全被优化掉。 由于类型擦除,运行时系统无法在运行时执行更有用的类型检查。

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

请参阅:什么是“未检查”警告?

A warning by which the compiler indicates that it cannot ensure type safety.
The term "unchecked" warning is misleading. It does not mean that the warning is unchecked in any way. The term "unchecked" refers to the fact that the compiler and the runtime system do not have enough type information to perform all type checks that would be necessary to ensure type safety. In this sense, certain operations are "unchecked".

The most common source of "unchecked" warnings is the use of raw types. "unchecked" warnings are issued when an object is accessed through a raw type variable, because the raw type does not provide enough type information to perform all necessary type checks.

Example (of unchecked warning in conjunction with raw types):

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");  
                      ^

When the add method is invoked the compiler does not know whether it is safe to add a String object to the collection. If the TreeSet is a collection that contains String s (or a supertype thereof), then it would be safe. But from the type information provided by the raw type TreeSet the compiler cannot tell. Hence the call is potentially unsafe and an "unchecked" warning is issued.

"unchecked" warnings are also reported when the compiler finds a cast whose target type is either a parameterized type or a type parameter.

Example (of an unchecked warning in conjunction with a cast to a parameterized type or type variable):

  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;

A cast whose target type is either a (concrete or bounded wildcard) parameterized type or a type parameter is unsafe, if a dynamic type check at runtime is involved. At runtime, only the type erasure is available, not the exact static type that is visible in the source code. As a result, the runtime part of the cast is performed based on the type erasure, not on the exact static type.

In the example, the cast to Wrapper would check whether the object returned from super.clone is a Wrapper , not whether it is a wrapper with a particular type of members. Similarly, the casts to the type parameter T are cast to type Object at runtime, and probably optimized away altogether. Due to type erasure, the runtime system is unable to perform more useful type checks at runtime.

In a way, the source code is misleading, because it suggests that a cast to the respective target type is performed, while in fact the dynamic part of the cast only checks against the type erasure of the target type. The "unchecked" warning is issued to draw the programmer's attention to this mismatch between the static and dynamic aspect of the cast.

Please refer: What is an "unchecked" warning?

一曲琵琶半遮面シ 2024-08-02 22:57:42

@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

@SuppressWarnings annotation is one of the three built-in annotations available in JDK and added alongside @Override and @Deprecated in Java 1.5.

@SuppressWarnings instruct the compiler to ignore or suppress, specified compiler warning in annotated element and all program elements inside that element.
For example, if a class is annotated to suppress a particular warning, then a warning generated in a method inside that class will also be separated.

You might have seen @SuppressWarnings("unchecked") and @SuppressWarnings("serial"), two of most popular examples of @SuppressWarnings annotation. Former is used to suppress warning generated due to unchecked casting while the later warning is used to remind about adding SerialVersionUID in a Serializable class.

Read more: https://javarevisited.blogspot.com/2015/09/what-is-suppresswarnings-annotation-in-java-unchecked-raw-serial.html#ixzz5rqQaOLUa

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文