Reputation: 123
I once read that Java Generics brings the type safety that was previously missed with handling Object references and including explicit casts by making all casts implicit and automatic. I studied Generics and understand its mechanics, but I still can't see how automatically generated implicit casts brings type safety over explicit casts that were used prior to Generics - I mean, I still could use explicit casts and achieve the same effect.. ?
Generics seems to have simply streamlined the process by taking what had been a sole programming approach on the programmer's side and make into a feature of the language, simplifying the process by really handling/adjusting code for the programmer..?
Upvotes: 0
Views: 3259
Reputation: 4499
Consider the example
HashMap<String, Integer> map = new HashMap<String, Integer>();
Set<String> st = map.keySet(); // This will only contain String objects
In this example it ensures that st
will only contain String objects. This reduces the possibility of run time errors due casting.
Additionally
Set<String> st = new Set<String>();
st.add("a"); // allowed
st.add('a'); // compile time error
Here the compile time error will identify the problem, so hours debugging can be avoided.
Upvotes: 0
Reputation: 131346
but I still can't see how automatically generated implicit casts brings type safety over explicit casts that were used prior to Generics -
You have not a automatically generated implicit cast (downcast) in raw types, you have to explicit cast from Object
to a specific type as a raw type can take any Object
and the problem is there.
For example here you don't have type safety as you can put anything in a List that functionally should contain only String
:
List listOfString = new ArrayList();
listOfString.add("myString"); // compile
listOfString.add(5); // compile (not a String)
String expectedStringButNot = (String) listOfString.get(1); // ClassCastException at runtime
With generics, you have type safety as you could not put anything in a List that functionally should contain only String
as the compiler will stop before :
List<String> listOfString = new ArrayList<>();
listOfString.add("myString"); // compile
listOfString.add(5); // doesn't compile (not a String)
Upvotes: 4
Reputation: 22977
To answer your question: indeed, generics are in fact designed to provide additional compile-time checking. Stronger than that, generic types are erased at runtime. They provide no additional "functionality" to Java itself.
Generic kind of 'replaced' some casts that were needed when generic weren't there.
// My list of strings
List list = new ArrayList();
list.add("Hello");
String str1 = list.get(0); // Won't work
String str2 = (String) list.get(0);
The compiler was simply not sure that the list only contained String object, although the programmer was sure he only put Strings in it.
// My list of strings
List<String> list = new ArrayList<>(); // <> means <String> in this case
list.add("Hello");
String str1 = list.get(0); // works
String str2 = (String) list.get(0); // The typecast is unnecessary,
// for the compiler already knows
// that the list could only contain
// strings
So in the first code snippet, the typecast to String
was necessary because you simply got an Object
from the list. In the second snippet however, the typecast is made unnecessary.
Upvotes: 1