1

How can I instantiate a new Object of a generic class inside of a generic method, exactly with the same type that is passed (as type) to that method?

(Something like passing a variable from method parameters to a class constructor.)


Example: Both B and C are derived from A. I want the T in the new instance of GenericClass (that is instantiated in the genericMethod and named genericClassT) to be B or C (dependent on genericMethod invoking).

class A {}
class B extends A {}
class C extends A {}

abstract class GenericClass<T extends A> { ... }

public static void main(String[] args) {
    ...
    genericMethod(B.class);
    genericMethod(C.class); 
}

<T extends A> boolean genericMethod(Class<T> tClass) {
    final GenericClass<T> genericClassT = new GenericClass<T>() {
        @Override void test(T input) {}
    }; // THE PROBLEM IS HERE:
       // The T(s) in this statement aren't the same T that passed to method!
       // They Are `A` always (not `B` or `C`). How can I pass the same T that passed to the method?

    ...
}

Full Test (genericMethod in the below code renamed for better meaning):

class A {}
class B extends A {}
class C extends A {}

abstract class GenericClass<T extends A> {
    boolean is_T_equals_to_B() {
        try {
            test((T) new B());
            return true;
        } catch (ClassCastException e) {
            return false;
        }
    }
    abstract void test (T input);
}

public static void main(String[] args) {
    final GenericClass<B> genericClassB = new GenericClass<B>() {
        @Override void test(B input) {}
    };

    final GenericClass<C> genericClassC = new GenericClass<C>() {
        @Override void test(C input) {}
    };

    // These work fine:
    System.out.println(genericClassB.is_T_equals_to_B());  // prints true
    System.out.println(genericClassC.is_T_equals_to_B());  // prints false

    // These don't work:
    System.out.println(is_T_equals_to_B_in_inner_instance(B.class));  // prints true
    System.out.println(is_T_equals_to_B_in_inner_instance(C.class));  // prints true ... I don't want this!
}

<T extends A> boolean is_T_equals_to_B_in_inner_instance(Class<T> tClass) {
    final GenericClass<T> genericClassT = new GenericClass<T>() {
        @Override void test(T input) {}
    }; // THE PROBLEM IS HERE:
       // The T(s) in this statement aren't the same T that passed to method!
       // They Are `A` actually (not `B` or `C`). How can I pass the same T that passed to the method?

    return genericClassT.is_T_equals_to_B();
}
Mir-Ismaili
  • 13,974
  • 8
  • 82
  • 100
  • 1
    Generics are a compile-time constraint, so your test is meaningless. Read up on [type erasure](https://docs.oracle.com/javase/tutorial/java/generics/erasure.html) and [bridge methods](https://docs.oracle.com/javase/tutorial/java/generics/bridgeMethods.html). – shmosel Dec 04 '17 at 07:04
  • @shmosel; My **Full Test** works. – Mir-Ismaili Dec 04 '17 at 07:09
  • Then what's your question? – shmosel Dec 04 '17 at 07:09
  • @shmosel; It has two parts. Part 1 is as it should be and Part 2 not. My question is why the first part works and the second not and how to correct the second part? Or perhaps it's impossible and is irrelevant to the first part. Then I want to understand why? – Mir-Ismaili Dec 04 '17 at 07:19
  • Part 1 creates type-specific bridge methods. Part 2 is subject to standard type erasure. See the links in my earlier comment for more info. The best you can do is test `tClass.isInstance(new B())` or `B.class.isAssignableFrom(tClass)`. – shmosel Dec 04 '17 at 07:23
  • Have you tried [Class.newInstance()](https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#newInstance--) – OldCurmudgeon Dec 04 '17 at 07:41

0 Answers0