Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java raw type value assigned to generic type run time getClss() method error

Tags:

public class Box<T> {
    private T t;
    public Box(T t){
        this.t = t;
    }
    public void add(T t) {
      this.t = t;
    }
    public T get() {
      return t;
    }
    public static void main(String[] args) {
      Box<Integer> b = new Box(new String("may be"));
      System.out.println(b.get()); // successfully print out "may be"
      System.out.println(b.get().getClass()); // error
   }
}

This code gives a runtime error:

exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
  1. why is b.get() not triggering a runtime error?
  2. why does an runtime error occur only when I try to get the class of the class variable?

To be more precise: why is the compiler inserting a checkcast instruction into the bytecode only for the second get() (leading to the exception)?

like image 750
woodybird Avatar asked Aug 18 '17 12:08

woodybird


People also ask

Which is raw type of generic Box in Java?

Box rawBox = new Box(); Therefore, Box is the raw type of the generic type Box<T>. However, a non-generic class or interface type is not a raw type. The warning shows that raw types bypass generic type checks, deferring the catch of unsafe code to runtime.

How to declare generic in Java?

A Generic Version of the Box Class To update the Box class to use generics, you create a generic type declaration by changing the code "public class Box" to "public class Box<T>". This introduces the type variable, T, that can be used anywhere inside the class.

What is generic data type in Java?

Generics means parameterized types. The idea is to allow type (Integer, String, … etc., and user-defined types) to be a parameter to methods, classes, and interfaces. Using Generics, it is possible to create classes that work with different data types.

Do generics prevent type cast errors?

Implementing generics into your code can greatly improve its overall quality by preventing unprecedented runtime errors involving data types and typecasting.


1 Answers

Please note:

  • in the first case, the result of get() is used for println(Object): in other words: the receiving side expects an Object, and that "condition" will always be true.
  • in the second case, a method invocation on the returned object will follow. And now it makes can make a huge difference if the returned type is the expected one. Therefore the compiler is adding this check to guarantee that the following method call is sound.

As background, one can look into the Java Language Specification, chapter 5.52:

The cast is a checked cast.

Such a cast requires a run-time validity check. If the value at run time is null, then the cast is allowed. Otherwise, let R be the class of the object referred to by the run-time reference value, and let T be the erasure (§4.6) of the type named in the cast operator. A cast conversion must check, at run time, that the class R is assignment compatible with the type T, via the algorithm in §5.5.3.

respectively chapter 5.53 Checked Casts at Run Time.

like image 101
GhostCat Avatar answered Oct 11 '22 14:10

GhostCat