This came up as a question I asked in an interview recently as something the candidate wished to see added to the Java language. It\'s commonly-identified as a pain that Jav
You'd be able to create generic arrays in your code.
public <T> static void DoStuff() {
T[] myArray = new T[42]; // No can do
}
My exposure to Java Geneircs is quite limited, and apart from the points other answers have already mentioned there is a scenario explained in the book Java Generics and Collections, by Maurice Naftalin and Philip Walder, where the reified generics are useful.
Since the types are not reifiable, it is not possible to have Parameterized exceptions.
For example the declaration of below form is not valid.
class ParametericException<T> extends Exception // compile error
This is because the catch clause checks whether the thrown exception matches a given type. This check is same as the check performed by instance test and since the type is not reifiable the above form of statement is invalid.
If the above code was valid then exception handling in the below manner would have been possible:
try {
throw new ParametericException<Integer>(42);
} catch (ParametericException<Integer> e) { // compile error
...
}
The book also mentions that if Java generics are defined similar to the way C++ templates are defined (expansion) it may lead to more efficient implementation as this offers more opportunities for optimization. But doesn't offer any explanation more than this, so any explanation (pointers) from the knowledgeable folks would be helpful.
From the few times that I came across this "need", it ultimately boils down to this construct:
public class Foo<T> {
private T t;
public Foo() {
this.t = new T(); // Help?
}
}
This does work in C# assuming that T
has a default constructor. You can even get the runtime type by typeof(T) and get the constructors by Type.GetConstructor().
The common Java solution would be to pass the Class<T>
as argument.
public class Foo<T> {
private T t;
public Foo(Class<T> cls) throws Exception {
this.t = cls.newInstance();
}
}
(it does not necessarily need to be passed as constructor argument, as a method argument is also fine, the above is just an example, also the try-catch
is omitted for brevity)
For all other generic type constructs, the actual type can easily be resolved with a bit help of reflection. The below Q&A illustrate the use cases and possibilities:
This is an old question, there are a ton of answers, but I think that the existing answers are off the mark.
"reified" just means real and usually just means the opposite of type erasure.
The big problem related to Java Generics:
void method(List<A> l)
and method(List<B> l)
. This is due to type erasure but is extremely petty.It's not that you will achieve anything extraordinary. It will just be simpler to understand. Type erasure seems like a hard time for beginners, and it ultimately requires one's understanding on the way the compiler works.
My opinion is, that generics are simply an extra that saves a lot of redundant casting.
Something that all the answers here have missed that is constantly a headache for me is since the types are erased, you cannot inherit a generic interface twice. This can be a problem when you want to make fine grained interfaces.
public interface Service<KEY,VALUE> {
VALUE get(KEY key);
}
public class PersonService implements Service<Long, Person>,
Service<String, Person> //Can not do!!