nz_21
nz_21

Reputation: 7343

Understand Type Erasure in Java

How would one implement generics without type erasure? As I understand it, if I have class Foo<T>, the T is replaced basically replaced with Object and the compiler only has metadata that helps it cast it to the right paramterized type.

But, if reification was implemented, then the T would be the actual parameterized type (as opposed to Object)... But I don't understand how the compiler would then able to figure out if new T() is valid invocation (i.e, T might not have a no-arg constructor).

Upvotes: 1

Views: 137

Answers (1)

Kr&#246;w
Kr&#246;w

Reputation: 319

In Java specifically, constructors are not inherited by subclasses, so as long as a given parameterized type T can't be narrowed down to a specific type, you wouldn't be able to run new T(), since Java is statically typed, regardless of whether or not reification happens. However, instantiation using new is only one case where classes are used.

Instanceof

The most obvious use to me for generics that aren't erased is being able to use T in an instanceof expression:

class Box<T> {
   public boolean isInst(Object obj) {
      return obj instanceof T;
   }
}

There's also the idea of seeing if T is a superclass or subclass of other classes, or checking equality with classes.

Static Methods

With reification, Java would be able to call static methods on T "correctly." Let's say we have the following classes:

class Parent {
   void doSomething() { System.out.println("Parent"); }
}

class Child extends Parent {
   void doSomething() { System.out.println("Child"); }
}

With those defined, then the following code...

class Box<T extends Parent> {

   void test() { T.doSomething(); }

   public static void main(String...args) {
      Box<Parent> parentBox = new Box<>();
      Box<Child> childBox = new Box<>();

      parentBox.test();
      childBox.test();
   }
}

...should print:

Parent
Child

but instead prints:

Parent
Parent

This is because T turns into Parent by erasure.

Inheritance

Generic inheritance (as weird as it sounds) could (probably) exist:

public class GenericType<T> {
   public class Inner extends T {   }

   public static void main(String...args) {
      GenericType<MyClass>.Inner obj = new GenericType<MyClass>().new Inner();
      System.out.println(obj instanceof MyClass); // Prints true
   }
}

Upvotes: 2

Related Questions