ChatGPT解决这个技术问题 Extra ChatGPT

What is SuppressWarnings ("unchecked") in Java?

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

@SuppressWarnings("unchecked")

What does this mean?


J
Jon Skeet

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.


In some cases, you can avoid it by using YourClazz.class.cast(). Works for single generic element containers but not for collections.
Or preferably use wildcard generics (YourClazz<?>) - Java never warns about such casts as they are safe. This won't always work however (see generics FAQ for details).
K
Keshaw Kumar

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)."


a
akarnokd

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

D
Daniel Perník

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


This is a good example for the situation where we need to use SuppressWarnings.
d
drac_o

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.


Your SupressWarning link is dead; here's an alternative: docs.oracle.com/javase/specs/jls/se6/html/…
K
Konrad Borowski

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.


B
Bill the Lizard

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

B
Bilesh Ganguly

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;

B
BakerTheHacker

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.


JDK5 is new? It has completed most of its End of Service Life period.
I know that JDK 5 is rather outdated, what I meant was that, it is new in the sense that it introduced new features to Java, previously not offered in JDK 4. Also note that there those still awaiting JDK 7 before leaving JDK 5 behind in order to embrace JDK 6, I cannot reason why!
K
Konrad Borowski

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?


M
Majid Roustaei

@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