For example, with a List of Strings, prior to 1.5 you might write:
List myList = new ArrayList();
myList.add("hello");
myList.add("goodbye");
// myList.add(new Date()); This would compile but cause failures later
Iterator it = myList.iterator();
while (it.hasNext()) {
String s = (String)it.next();
System.out.println(s);
}
In 1.5 you can write this as:
List<String> myList = new ArrayList<String>();
myList.add("hello");
myList.add("goodbye");
// myList.add(new Date()); This won't compile!
Iterator<String> it = myList.iterator();
while (it.hasNext()) {
String s = it.next();// Look Ma, no downcast!
System.out.println(s);
}
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
When you take an element out of a Collection, you must cast it to the type of element that is stored in the collection. Besides being inconvenient, this is unsafe. The compiler does not check that your cast is the same as the collection's type, so the cast can fail at run time.
Generics provides a way for you to communicate the type of a collection to the compiler, so that it can be checked. Once the compiler knows the element type of the collection, the compiler can check that you have used the collection consistently and can insert the correct casts on values being taken out of the collection.
Here is a simple example taken from the existing Collections tutorial:
// Removes 4-letter words from c. Elements must be strings
static void expurgate(Collection c) {
for (Iterator i = c.iterator(); i.hasNext(); )
if (((String) i.next()).length() == 4)
i.remove();
}
Here is the same example modified to use generics:
// Removes the 4-letter words from c
static void expurgate(Collection<String> c) {
for (Iterator<String> i = c.iterator(); i.hasNext(); )
if (i.next().length() == 4)
i.remove();
}
When you see the code <Type>, read it as �of Type�; the declaration above reads as �Collection of String c.� The code using generics is clearer and safer. We have eliminated an unsafe cast and a number of extra parentheses. More importantly, we have moved part of the specification of the method from a comment to its signature, so the compiler can verify at compile time that the type constraints are not violated at run time. Because the program compiles without warnings, we can state with certainty that it will not throw a ClassCastException at run time. The net effect of using generics, especially in large programs, is improved readability and robustness.
To paraphrase Generics Specification Lead Gilad Bracha, when we declare c to be of type Collection<String>, this tells us something about the variable c that holds true wherever and whenever it is used, and the compiler guarantees it (assuming the program compiles without warnings). A cast, on the other hand, tells us something the programmer thinks is true at a single point in the code, and the VM checks whether the programmer is right only at run time.
While the primary use of generics is collections, there are many other uses. �Holder classes,� such as WeakReference and ThreadLocal, have all been generified, that is, they have been retrofitted to make use of generics. More surprisingly, class Class has been generified. Class literals now function as type tokens, providing both run-time and compile-time type information. This enables a style of static factories exemplified by the getAnnotation method in the new AnnotatedElement interface:
<T extends Annotation> T getAnnotation(Class<T> annotationType);
This is a generic method. It infers the value of its type parameter T from its argument, and returns an appropriate instance of T, as illustrated by the following snippet:
Author a = Othello.class.getAnnotation(Author.class);
Prior to generics, you would have had to cast the result to Author. Also you would have had no way to make the compiler check that the actual parameter represented a subclass of Annotation.
Generics are implemented by type erasure: generic type information is present only at compile time, after which it is erased by the compiler. The main advantage of this approach is that it provides total interoperability between generic code and legacy code that uses non-parameterized types (which are technically known as raw types). The main disadvantages are that parameter type information is not available at run time, and that automatically generated casts may fail when interoperating with ill-behaved legacy code. There is, however, a way to achieve guaranteed run-time type safety for generic collections even when interoperating with ill-behaved legacy code.
The java.util.Collections class has been outfitted with wrapper classes that provide guaranteed run-time type safety. They are similar in structure to the synchronized and unmodifiable wrappers. These �checked collection wrappers� are very useful for debugging. Suppose you have a set of strings, s, into which some legacy code is mysteriously inserting an integer. Without the wrapper, you will not find out about the problem until you read the problem element from the set, and an automatically generated cast to String fails. At this point, it is too late to determine the source of the problem. If, however, you replace the declaration:
Set<String> s = new HashSet<String>();
with this declaration:
Set<String> s = Collections.checkedSet(new HashSet<String>(), String.class);
the collection will throw a ClassCastException at the point where the legacy code attempts to insert the integer. The resulting stack trace will allow you to diagnose and repair the problem.
You should use generics everywhere you can. The extra effort in generifying code is well worth the gains in clarity and type safety. It is straightforward to use a generic library, but it requires some expertise to write a generic library, or to generify an existing library. There is one caveat: You may not use generics (or any other Tiger features) if you intend to deploy the compiled code on a pre-1.5 virtual machine.
If you are familiar with C++'s template mechanism, you might think that generics are similar, but the similarity is superficial. Generics do not generate a new class for each specialization, nor do they permit �template metaprogramming.�
There is much more to learn about generics
SCJA,SCJP,SCWCD,SCBCD,SCEA I
Java Developer, Thailand
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
seems like the new 1.5 code fix the type of objects that the list can contain and compiler is able to check it without the help of the application...
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Originally posted by Nicholas Cheung:
Basically, I am new to Generics in Java.![]()
Ko Ko, Could you breifly explain what is it about? Is it just a common type for displaying all its sub-classes info? Or... ?
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
Originally posted by Nicholas Cheung:
Ko Ko,
FYI. Pradeep has posted a link to a good article in the thread:
https://coderanch.com/t/374339/java/java/Java-Tiger-New-Features-Reader
You may have a look as well.![]()
Nick
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
Originally posted by Nicholas Cheung:
Thanks somkiat.
I am already reading the PDF mentioned by Pradeep.![]()
In such sense, seems Generics only work for Collection, rite?
Nick
SCJA,SCJP,SCWCD,SCBCD,SCEA I
Java Developer, Thailand
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Originally posted by Pradeep Bhat:
That is right. Generic will provide you the runtime type safety which will avoid lot of errors. You will be sure that the ArrayList contains only String and you will be able to code without any ClassCastException.
Prior to tiger you would be expected to cast every time you retrive objects from collections. With the power of tigeryou dont need to cast which is lot useful.
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Originally posted by Pradeep Bhat:
(...)
Prior to tiger you would be expected to cast every time you retrive objects from collections. With the power of tigeryou dont need to cast which is lot useful.
I've heard it takes forever to grow a woman from the ground
For my latest books on Java, including Introducing JavaFX 8 Programming, see HerbSchildt.com
Originally posted by Joseph George:
The reason I'm a bit apprehensive about generics is that they're magic. When I started learning java, everything seemed like magic, I just copied code from somewhere and it did what the book said it should. But then you begin to realize, there are a VERY limited 'rules' in java. When you say System.whatever, you're not just typing a magic keyword, you're just dealing with static members of a class. Back in turtle graphics when I said pen.move(19), it's not code word, it's just a method on an object. All the rules are right there. But angle brackets?! <String>? that doesn't resolve to the basic rules. Knowing how objects work is not enough to get through generics. And don't ever try to tell me it removes clutter. Type casts may be phyisically clutter, but they obey the rules, they make sense, and the mental clutter is 0. The object rules all make sense, and accomplish everything you need to. Magic scares me. There's the entire, well-worked out object system, and then they have to go and add an extra bell/wistle that doesn't fit with the rest, doesn't meld.
I don't like change.
Originally posted by Layne Lund:
I'm certain that if you care to learn these new rules, you will see that generics follow them quite well.
I've heard it takes forever to grow a woman from the ground
For example, with a List of Strings, prior to 1.5 you might write:
List myList = new ArrayList();
myList.add("hello");
myList.add("goodbye");
// myList.add(new Date()); This would compile but cause failures later
Iterator it = myList.iterator();
while (it.hasNext()) {
String s = (String)it.next();
System.out.println(s);
}
String s = it.next(); // Look Ma, no downcast!
I've heard it takes forever to grow a woman from the ground
For my latest books on Java, including Introducing JavaFX 8 Programming, see HerbSchildt.com
Originally posted by Stefan Wagner:
to have a typesafe collection and avoid permanent casting.
Of course, every serious programer made a small Template-class, which could be populated by the needed type:
generate_javalist Foo
This templates can now be thrown away.![]()
Originally posted by Herb Schildt:
Prior to generics, all "generic" code had to operate on objects of type Object. This made runtime type-mismatches possible. It also prevented the compiler from being able to ensure that a collection, for example, contained only the types of objects that you really entended for it to contain. With generics, the compiler can ensure type compatibility, and prevent runtime errors.
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
"I'm not back." - Bill Harding, Twister
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Java generics do give up a certain amount of power for this safety, of course.
SCJA,SCJP,SCWCD,SCBCD,SCEA I
Java Developer, Thailand
Originally posted by Pradeep Bhat:
No they are not atleast for me. The real benefit is that there is no chance of ClassCastException. Isn't that good? :roll:
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
SCJP 1.2, OCP 9i DBA, SCWCD 1.3, SCJP 1.4 (SAI), SCJD 1.4, SCWCD 1.4 (Beta), ICED (IBM 287, IBM 484, IBM 486), SCMAD 1.0 (Beta), SCBCD 1.3, ICSD (IBM 288), ICDBA (IBM 700, IBM 701), SCDJWS, ICSD (IBM 348), OCP 10g DBA (Beta), SCJP 5.0 (Beta), SCJA 1.0 (Beta), MCP(70-270), SCBCD 5.0 (Beta), SCJP 6.0, SCEA for JEE5 (in progress)
Originally posted by Nicholas Cheung:
But honestly, the developers should always make sure the type of the target objects, before accessing them, isnt it?![]()
Nick
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
But honestly, the developers should always make sure the type of the target objects, before accessing them, isnt it?
Originally posted by Pradeep Bhat:
It would have been great If developers could code properly but human beings make mistake. So leave this job to compiler and code without worry.![]()
Originally posted by Gregg Bolinger:
Not to mention the fact that you might provide a class that takes a collection of String objects and Jo Henry in the other cubicle decides to use your class, he might forget or not know it only takes Strings. So he will find out at compile time rather than runtime and this will save some headaches.
Co-author of SCMAD Exam Guide, Author of JMADPlus
SCJP1.2, CCNA, SCWCD1.4, SCBCD1.3, SCMAD1.0, SCJA1.0, SCJP6.0
Books: Pragmatic Unit Testing in Java, Agile Java, Modern C++ Programming with TDD, Essential Java Style, Agile in a Flash. Contributor, Clean Code.
I submit that this exception originates not from shortcomings in Java, but from simple poor programming. Keep track of your lists, and this will NEVER be a problem.
A good workman is known by his tools.
Did you see how Paul cut 87% off of his electric heat bill with 82 watts of micro heaters? |