Search code examples
javagenericsincompatibletypeerror

How and when does Class T change from Integer to String rather than showing error/exception


What i have done is to just get to know how Generics works in Java. I have written the following code:

public class Test {

    public static void main(String... args) throws Exception{  
        Foo o = new Foo<Integer>(new Integer(5));
        o.fun();
    }
}       

class Foo<T> {

    private T t;

    public Foo(T t) throws InstantiationException, IllegalAccessException{
       System.out.println("1. T is "+t.getClass());
       this.t = (T)"test";
       System.out.println("2. T is "+t.getClass());
   }

   void fun(){
       System.out.println("3. T is "+t.getClass()+" t = "+t);
   }
}

And output is

1. T is class java.lang.Integer
2. T is Still class java.lang.Integer
3. T is class java.lang.String t = test

My question is Why this is changing Class from Integer to String and not showing error/exception.

And second thing is that when I write t = 9; in function fun(), it shows:

incompatible types
required: T
found:    java.lang.Integer

How do generic classes work and how are they used?

Your response will be greatly appreciated!!


Solution

  • You have declared a generic with no upper bound. Replacement for an unbounded generic is Object itself

    This means, when the class file gets generated your Foo<T> class looks something like this

    class Foo {
    
        private Object t;
    
        public Foo(Object  t) throws InstantiationException, IllegalAccessException{
           System.out.println("1. T is "+t.getClass());
           this.t = (Object)"test";
           System.out.println("2. T is "+t.getClass());
       }
    
       void fun(){
           System.out.println("3. T is "+t.getClass()+" t = "+t);
       }
    }
    

    This is due to the fact that, generics are only there to ensure compile time type safety . In run-time they are erased

    Considering this

    this.t = (Object)"test";
    

    is a valid statement, because Object is super class of all the classes and this.t then on becomes a String

    The reason for 2. T is Still class java.lang.Integer ,

    • here t is a parameter to the constructor and the parameter still points to Integer (not overwritten)
    • and the parameter takes precedence over this.t