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

joj*_*ojo 419 java generics unchecked suppress-warnings

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

@SuppressWarnings("unchecked")
Run Code Online (Sandbox Code Playgroud)

这是什么意思?

Jon*_*eet 398

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

当我嘲笑通用界面时,我通常会发现这很痛苦,但也有其他例子.通常值得尝试找出一种避免警告而不是抑制警告的方法(Java Generics常见问题解答在这里有帮助),但有时即使可能,也会使代码变形,以至于抑制警告更加整洁.在这种情况下总是添加解释性注释!

相同的泛型FAQ有关于此主题的几个部分,从"什么是未经检查的"警告开始? - 非常值得一读.

  • 在某些情况下,您可以使用YourClazz.class.cast()来避免它.适用于单个通用元素容器,但不适用于集合. (10认同)

Ben*_*key 49

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

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

SuppressWarnings

此外,Oracle还提供了一些有关注释用法的教程文档:

注释

正如他们所说,

"当与泛型出现之前编写的遗留代码接口时,可能会发生'未经检查'的警告(在标题为Generics的课程中讨论过)."


aka*_*okd 19

这也可能意味着当前的Java类型系统版本不适合您的情况.有几个JSR命题 /黑客来解决这个问题:类型标记,超类型标记,Class.cast().

如果你真的需要这种抑制,尽可能地缩小范围(例如,不要把它放在类本身或长方法上).一个例子:

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

   Collections.reverse(list);
   return list;
}
Run Code Online (Sandbox Code Playgroud)


Bra*_*lor 9

SuppressWarning注解用来打压注释元素编译器警告.具体来说,该unchecked类别允许抑制由于未经检查的类型转换而生成的编译器警告.


Dan*_*ník 8

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

JPA服务方法例如:

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

如果我没有在这里分配@SuppressWarnings("未选中"),那么就会出现问题,我希望返回我的ResultList.

在快捷方式类型安全意味着:如果程序在没有错误和警告的情况下编译并且在运行时不会引发任何意外的ClassCastException,则该程序被认为是类型安全的.

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

  • 对于我们需要使用SuppressWarnings的情况,这是一个很好的例子. (2认同)

Kon*_*ski 8

在Java中,泛型是通过类型擦除来实现的.例如,以下代码.

List<String> hello = List.of("a", "b");
String example = hello.get(0);
Run Code Online (Sandbox Code Playgroud)

编译如下.

List hello = List.of("a", "b");
String example = (String) hello.get(0);
Run Code Online (Sandbox Code Playgroud)

List.of定义为.

static <E> List<E> of(E e1, E e2);
Run Code Online (Sandbox Code Playgroud)

哪种类型的擦除变成了.

static List of(Object e1, Object e2);
Run Code Online (Sandbox Code Playgroud)

编译器在运行时不知道什么是泛型类型,所以如果你写这样的东西.

Object list = List.of("a", "b");
List<Integer> actualList = (List<Integer>) list;
Run Code Online (Sandbox Code Playgroud)

Java虚拟机在运行程序时不知道通用类型是什么,因此编译和运行,就像Java虚拟机一样,这是一个强制转换List类型(这是它唯一可以验证的东西,所以它只验证它).

但现在添加这一行.

Integer hello = actualList.get(0);
Run Code Online (Sandbox Code Playgroud)

ClassCastException当Java编译器插入一个隐式转换时,JVM会抛出一个意想不到的东西.

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer
Run Code Online (Sandbox Code Playgroud)

一个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;
}
Run Code Online (Sandbox Code Playgroud)

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


小智 5

您可以禁止编译器警告,并告诉泛型,您编写的代码是合法的.

例:

@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;
 }
Run Code Online (Sandbox Code Playgroud)


小智 5

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

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {}
Run Code Online (Sandbox Code Playgroud)

然后你可以在演员之前用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;
Run Code Online (Sandbox Code Playgroud)