Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use the class field on an ArrayList<T> instance in Java?

I have this code, which compiles:

new TypeToken<ArrayList<ServerTask>>() {}.getType()

Then I have tried

ArrayList<ServerTask>.class

which does not compile.

I am new to Java programming (came from C#) and I have thought that T.class is an exact equivalent of typeof(T) in C#. Apparently there is something really basic that I do not understand, so my question is what is wrong with ArrayList<ServerTask>.class and do I have no choice, but use new TypeToken<ArrayList<ServerTask>>() {}.getType() instead? Is there a shorter (nicer, saner) form?

Thanks.

like image 572
mark Avatar asked Sep 22 '11 08:09

mark


1 Answers

Unfortunately (?) Java implements generics using Type Erasure.

This means that there is no construct to get the generic type, and at runtime your ArrayList actually only stores Objects.

To be exact, Generics in Java are a compile-time only construct. They guarantee type-safety at compile time only.

EDIT: I just noticed this bit of code -

new TypeToken<ArrayList<ServerTask>>() {}.getType()

This is a workaround for the limitations of type erasure. Type information is preserved if you extend a generic class with a specific type. For example:

public interface List<T> {
}

public class StringList implements List<String> {
  // The bytecode of this class contains type information.
}

In your example, you are trivially extending the class TypeToken, causing the compiler to generate an anonymous inner class that contains the type information. The implementation of TypeToken.getType() will use reflection to give you this type information.

EDIT2: For a more detailed explanation, have a look at Reflecting Generics.

like image 132
Bringer128 Avatar answered Sep 27 '22 20:09

Bringer128