As assylias pointed out, erasing Java will make this information inaccessible at runtime - and therefore need to be hacked.
Assuming myInterface has a getter for T , as in, MyInterface.getValue():T (or the hack should have added it), you could do something like this (ignoring the possibility of returning getValue() null ):
public <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){ return myInterface.getValue().getClass() }
Below is the full implementation
public class Q34271256 { public static interface MyInterface<T> { T getValue(); } public static class MyDoubleClass implements MyInterface<Double> { private final Double value; public MyDoubleClass(Double value) { this.value = value; } @Override public Double getValue() { return value; } } public static class MyIntegerClass implements MyInterface<Integer> { private final Integer value; public MyIntegerClass(Integer value) { this.value = value; } @Override public Integer getValue() { return value; } } @SuppressWarnings("unchecked") public static <T extends Number> Class<T> inferInstanceType(MyInterface<T> myInterface){ Number value = myInterface.getValue(); if (value == null) return null; return (Class<T>)value.getClass(); } public static void main(String...args) { List<MyInterface<? extends Number>> list = Arrays.asList( new MyDoubleClass(1.1), new MyIntegerClass(5) ); for (MyInterface<? extends Number> myInterface : list) { Class<?> type = inferInstanceType(myInterface); System.out.printf("%s inferred type is %s\n", myInterface.getClass().getName(), type.getName()); } } }
And the result should look something like this:
MyDoubleClass inferred type is java.lang.Double MyIntegerClass inferred type is java.lang.Integer
source share