Unchecked Assignment Java Generics Class

A raw type is the name of a generic class or interface without any type arguments. For example, given the generic class:

public class Box<T> { public void set(T t) { /* ... */ } // ... }

To create a parameterized type of , you supply an actual type argument for the formal type parameter :

Box<Integer> intBox = new Box<>();

If the actual type argument is omitted, you create a raw type of :

Therefore, is the raw type of the generic type . However, a non-generic class or interface type is not a raw type.

Raw types show up in legacy code because lots of API classes (such as the classes) were not generic prior to JDK 5.0. When using raw types, you essentially get pre-generics behavior — a gives you s. For backward compatibility, assigning a parameterized type to its raw type is allowed:

Box<String> stringBox = new Box<>(); Box rawBox = stringBox; // OK

But if you assign a raw type to a parameterized type, you get a warning:

Box rawBox = new Box(); // rawBox is a raw type of Box<T> Box<Integer> intBox = rawBox; // warning: unchecked conversion

You also get a warning if you use a raw type to invoke generic methods defined in the corresponding generic type:

Box<String> stringBox = new Box<>(); Box rawBox = stringBox; rawBox.set(8); // warning: unchecked invocation to set(T)

The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime. Therefore, you should avoid using raw types.

The Type Erasure section has more information on how the Java compiler uses raw types.

Unchecked Error Messages

As mentioned previously, when mixing legacy code with generic code, you may encounter warning messages similar to the following:

Note: Example.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details.

This can happen when using an older API that operates on raw types, as shown in the following example:

public class WarningDemo { public static void main(String[] args){ Box<Integer> bi; bi = createBox(); } static Box createBox(){ return new Box(); } }

The term "unchecked" means that the compiler does not have enough type information to perform all type checks necessary to ensure type safety. The "unchecked" warning is disabled, by default, though the compiler gives a hint. To see all "unchecked" warnings, recompile with .

Recompiling the previous example with reveals the following additional information:

WarningDemo.java:4: warning: [unchecked] unchecked conversion found : Box required: Box<java.lang.Integer> bi = createBox(); ^ 1 warning

To completely disable unchecked warnings, use the flag. The annotation suppresses unchecked warnings. If you are unfamiliar with the syntax, see Annotations.

« Previous • Trail • Next »

In this case, it is perfectly okay to suppress the unchecked cast warning.

It's an unchecked cast because is not known at runtime. So the runtime check can only check the cast up to (the erasure of ), but not actually up to itself. (So for example, if were , then if the object's actual runtime class was , it would not be caught by the check even though it's not .)

returns , and not (where would be the type argument of the parameter), because it can be used to create both arrays of primitives and arrays of references. Type variables like cannot represent primitive types, and the only supertype of array-of-primitive types is . objects representing primitive types are parameterized with its wrapper class as the type parameter, e.g. has type . But if you pass to , you will create an , not (which would be ). But if you pass a representing a reference type, will return an .

So basically, calling with a will always return either an , or an array of primitives. An array-of-primitives type is not a subtype of , so it would fail a runtime check for . In other words, if the result is an , it is guaranteed to be an . So even though this cast only checks up to at runtime, and it doesn't check the part from up to , in this case, the check up to is sufficient to guarantee that it is an , and so the unchecked part is not an issue in this case, and it is effectively a fully checked cast.

By the way, from the code you have shown, you do not need to pass a class object to initialize or to use . That would only be necessary if your class actually used the class at runtime. But it doesn't. All it does is create an array (that is not exposed to the outside of the class), and get elements from it. That can be achieved using an . You just need to cast to when you take an element out (which is unchecked by which we know to be safe if we only put s into it):

0 thoughts on “Unchecked Assignment Java Generics Class”


Leave a Comment

Your email address will not be published. Required fields are marked *