Domanda

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!!

È stato utile?

Soluzione

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

Altri suggerimenti

Here is your problem:

private T t;

t is a class variable here.

       System.out.println("1. T is "+t.getClass());
       this.t = (T)"test";
       System.out.println("2. T is "+t.getClass());

In above code in your sysout, the variable you are printing is 't' which is passed to method, not your class varible 't' declared above (this.t)

Class variable 't' got updated to 'String' Type, which gets printed in your "fun()" method.

' this.t = (T)"test";' this is wrong. you cant change type of class. firstly defined. in class T must be Integer because firstly you gave type as Integer generics example link

when you see ,replace all 'T' to 'Integer'. good hacking

Yes. Your declaration Foo o = new Foo<Integer>(new Integer(5)); should be Foo<Integer> o = new Foo<Integer>(new Integer(5)); (or if you're using Java 7 and above the diamond operator) like this Foo<Integer> o = new Foo<>(5));. The original fun() gets called on the base Foo (equivalend to Foo<Object> after type erasure). Which is to say it works like this

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

Also your constructor should be

this.t = (T) t;

And NOT this

this.t = (T)"test"; // Which is why you're getting a String!
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top