-1

So what makes a normal class, method vs a generic method or class is that the constructor for the class or method definition can take any type of argument value for Generics? I also read about and not sure about this but how all of the Generic argument values end up compiling to the same data type somehow in this concept called Type Erasure?

Also, if I did two instances like this

Test <String> sObj = new Test<String>("GeeksForGeeks");  
Test <Integer> sObj2 = new Test<Integer>(4);  

Assuming Test is a Generic class, I understand both are two different instances of Test class, but could I say these are two different types of Test class since both use two different Generic parameters, or would it be safe to say they both are same type of Test class objects if they end up compiling the same through Type Erasure I believe?

diya
  • 1
  • It kinda depends. Logically, I think it's fair to say that there are two different types here. However, due to implementation details, there is only one type at run time (that type being `Test`). What this means is that things that are possible in other languages are not possible in Java. "Type erasure" means that a programmer shouldn't expect their favorite tricks from C++ to work in Java. That's what I get out of it anyway. – markspace Aug 06 '20 at 04:25

1 Answers1

1

There are two different contexts to consider here: compile-time and run-time.

The difference between generic and non-generic classes at compile-time is the presence of one or more generic arguments in the signature of the class or method.

At compile time, Test<String> and Test<Integer> are treated as different types. The benefit of this is that if you try to use a Test<String> someplace where a Test<Integer> is expected, the compiler will complain.

sObj = sObj2; // compiler complains

This is good, because it was probably a simple mistake, which you want to catch and fix right away.

At run-time, each object has a little extra metadata associated with it to tell you what type it is. This is helpful for a lot of reasons, including Reflection (calling methods like .getClass()) and preventing invalid casts:

Object obj = "foo";
Integer i = (Integer) obj; // compiler doesn't complain, but an exception is thrown

Type Erasure means that this extra little bit of metadata contains no information about generic types at run time.

if(sObj.getClass().equals(sObj2.getClass())) { // This will be true
   sObj = (Test<String>) sObj1; // this will not produce an error.
}

There are some down-sides to this. For example, the code above is clearly where there's an error in the logic, but instead of seeing an invalid cast in the line above, you'll probably end up getting an invalid cast in a completely different part of code when you try to convert an Integer to a String.

But by the time the Java language added generics, implementing it any other way would have had a lot of other draw-backs in terms of effort and loss of backwards-compatibility. So they chose to use Type Erasure instead of Reified Generics.

See also: Why should I care that Java doesn't have reified generics?

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315