Iโm learning how libraries that create proxy objects work, I want to understand how they extract types from declared methods. For example, a popular library for Android - Upgrade:
interface MyService { @GET("path") Call<MyData> getData(); }
I was confused - how can I get exactly the MyData class from this interface, and not the raw Object? The reason from my understanding of type erasure will remove any information that fits inside common braces.
I wrote some test codes, and it is surprising to me that it is very easy to get a type from such code:
@org.junit.Test public void run() { Method[] methods = Test.class.getDeclaredMethods(); Method testMethod = methods[0]; System.out.println(testMethod.getReturnType()); ParameterizedType genericType = ((ParameterizedType) testMethod.getGenericReturnType()); Class<Integer> clazz = (Class<Integer>) genericType.getActualTypeArguments()[0]; System.out.println(clazz); } interface Test { List<Integer> test(); }
It looks a little dirty, but it works and prints Integer . This means that we have types at runtime. I also read about another dirty trick with anonymous classes:
System.out.println(new ArrayList<Integer>().getClass().getGenericSuperclass());
prints raw AbstractList<E> while this code
System.out.println(new ArrayList<Integer>() { }.getClass().getGenericSuperclass());
prints an ArrayList<Integer> .
And this is not the last thing that confused me. Kotlin has generic generics that look like hacked during compilation, but we can easily get a class from a generic one:
inline fun <reified T> test() { print(T::class) }
And now I'm completely confused with the type erase mechanism.
- Can someone explain why sometimes it stores information and sometimes not?
- Why are generics not implemented normally in Java? Yes, I read that this may break compatibility with previous versions, but I want to understand how to do this. Why doesn't the generic return type break anything other than
new ArrayList<Integer> ? - Why do anonymous classes have a common type and are not erased?
Updated: 4. How are generic generics created in Kotlin and why such a cool thing cannot be implemented in Java?
This explains a fairly clear idea of โโhow reconstituted generics work. @Mibac
You can only use reify in combination with the built-in function. such a function forces the compiler to copy the bytecode function to everyone where the function is used (the "Embed" function). When you call an inline function with type reified, the compiler knows the actual type used as the type argument and modifies the generated bytecode to use the corresponding class directly. Therefore, calls of type myVar: T becomes myVar - String, if the type of the argument was String, in bytecode and at run time.