I am still learning about generics and have a question. Say you had this generic class:
public class Test<T> {
public static void main (String[] args) {
Test t1 = new Test();
Test<String> t2 = new Test<String>();
Test t3 = new Test<String>();
}
}
All the statements compile but I don't really know what makes them different. Can anyone give me a brief explanation on those three statements.
The generic class works with multiple data types. A normal class works with only one kind of data type.
Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with collections like linked lists, hash tables, stacks, queues, trees, and so on.
super is a lower bound, and extends is an upper bound.
Test t1 = new Test();
Here you are using a Raw type. i.e., not passing an Type argument
for your generic clas
s.
Compiler should give you a warning here
Test is a raw type. References to generic type Test should be parameterized
Test<String> t2 = new Test<String>();
here you are using generics. passing String as a type argument
to your generic class
.
Test t3 = new Test<String>();
compiler should also give you a warning here too :
- Test is a raw type. References to generic type Test should be parameterized
same as your first case, but you are using parameterized type while invoking the constructor.
There is also another class which works fine in +java 7 versions.
Test<String> t4 = new Test<>();
No compiler warning here if you use + java 7 due to Type Inference
In this case due to introduction of type inference
generic type is inferred, thus you don't need to provide the generic type during constructor invokation.
Generics give you compile-time type checks.
It helps to add examples of what you can/can't do with your items (I've changed Test
to ArrayList
for ease of examples):
ArrayList t1 = new ArrayList();
ArrayList<String> t2 = new ArrayList();
ArrayList t3 = new ArrayList<String>();
// First list can have ANYTHING added to it
// Compiler won't check because no generics
t1.add(new Integer("7"));
t1.add("Hello");
// Second list can only have Strings added to it
// Compiler will check and throw compile error for anything else
t2.add(new Integer("7")); // doesn't compile
t2.add("Hello");
// Third list is interesting...
// Again, can have ANYTHING added to it
// This is because generics (in Java...) are swapped out at COMPILE time
// rather than RUNTIME. The compiler can see that the actual type is just
// plain ArrayList
// If you like, it's similar to doing:
// Object o = (String) new Object();
// The net-effect is everything reduced back to Object
t3.add(new Integer("7")); // fine
t3.add("Hello");
They all actually create identical objects. The only difference will be how they are treated syntactically in the rest of the code.
t1
and t3
will be treated in exactly the same way because they are the same type - they will be treated as an object with class Test
, nothing more.
t2
will be treated more rigorously in terms of type checking. If some opportunity presents itself for the compiler to make use of its generic <String>
quality then that quality will also be required to match.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With