The poem wrote: To the most despised cast We'll bid a fond farewell at last With generics' burning spear The need for cast will disappear
When you use a java.util.List to hold Strings, you would always have to cast to String when getting a value out.
List names = new ArrayList(); ... String name = (String)names.get(idx);
With generics, you can declare it a List<String> and the compiler can check that for you. It is used in a typesafe way and you don't have to cast when taking values out of the list. So the above example can be coded in this way:
List<String> names = new ArrayList<String>(); ... String name = names.get(idx);
Note: the J2SE 5.0 compiler will check the type for you. The ClassCastException may not be likely to be thrown, and you don't need to cast it back when you need the element of the collection.
One more example: Remove 4-letters words.
Current code: static void expurgate(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) { String s = (String) i.next(); if(s.length() == 4) i.remove(); } } Generics code static void expurgate(Collection<String> c) { for (Iterator<String> i = c.iterator(); i.hasNext(); ) if (i.next().length() == 4) i.remove(); }
Java generics are strongly typed, so you can only call a method that is a member of the "bound" of the type parameter. So, for example, you could define a generic method:
and this will constrain the type parameter to be some subclass or subinterface of Foo. If Foo has a method whatever(), this will be allowed, and is statically typechecked and typesafe..... void f(T t) { t.whatever(); }
For multiple bounds:
<T extends Interface1 & Interface2>
Note that & is used instead of ,(comma) to separate different type parameters.
The poem wrote: While Iterators have their uses They sometimes strangle us like nooses With enhanced-for's deadly ray Iterator's kept at bay
The enhanced for loop (also known as "foreach") lets you iterate over collections and arrays without using iterators or index variables.
Current code: void cancelAll(Collection c) { for (Iterator i = c.iterator(); i.hasNext(); ) { TimerTask tt = (TimerTask) i.next(); tt.cancel(); } } The J2SE 5.0 code would be: void cancelAll(Collection c) { for (Object o : c) ((TimerTask)o).cancel(); } The colon (:) is pronounced "in." or you can write it with two new features: void cancelAll(Collection<TimerTask> c) { for (TimerTask task : c) task.cancel(); }
The poem wrote: When from collections ints are drawn Wrapper classes make us mourn When Tiger comes, we'll shed no tears We'll autobox them in the ears
The J2SE 5.0 code: public class Freq { public static void main(String args[]) { Map<String, Integer> m = new TreeMap<String, Integer>(); for (String word : args) Integer freq = m.get(word); m.put(word, (feq == null? 1 : freq + 1)); System.out.println(m); } } The current code would be: public class Freq { private static final Integer ONE = new Integer(1); public static void main(String args[]) { Map m = new TreeMap(); for (int i=0; i<args.length; i++) { Integer freq = (Integer) m.get(args[i]); m.put(args[i], (freq==null ? ONE : new Integer(freq.intValue() + 1))); } System.out.println(m); } }
Note: The enum will be a keyword, so if you used it as an identifier in your old code, you'll have to change it in order to use -source 1.5.
The poem wrote: The int-enum will soon be gone like a foe we've known too long With typesafe-enum's mighty power Our foe will bother us no more
public enum Coin { penny(1), nickel(5), dime(10), quarter(25); Coin(int value) { this.value = value; } private final int value; public int value() { return value; } } public class CoinTest { public static void main(String[] args) { for (Coin c : Coin.values()) System.out.println(c + ": \t" + c.value() +"ยข \t" + color(c)); } private enum CoinColor { copper, nickel, silver } private static CoinColor color(Coin c) { switch(c) { case penny: return CoinColor.copper; case nickel: return CoinColor.nickel; case dime: case quarter: return CoinColor.silver; default: throw new AssertionError("Unknown coin: " + c); } } }
See how the constant declarations invoke a constructor, passing in an int that represents the value in cents? And see how the value is stored in a private field with a public accessor? See how we declare another enum for the colors? See how we can switch on enum constants? This is very useful when you want to "add a method" to an enum class, but you can't modify the class for whatever reason.
Actually, the new enums are more than mere structs in other languages. If you don't add any methods or fields, they're just "rich" typesafe enum constants. If you add methods or fields in, they are just full-fledged objects.
The poem wrote: And from the constant interface we shall inherit no disgrace With static import at our side, our joy will be unqualified
public interface Promotion { public static final double MANAGER_RATE = 0.59; public static final double SUPERVISER_RATE = 0.35; }
If you want to access Promotion interface, you class has to implement it. But in J2SE 5.0, you can import it in this way:
import static whatever.sub.Promotion; class Test { public static void main(String[] args) { double extra_salary = MANAGER_RATE * current_salary; ... } } Note: Promotion may be a class. It is good for constants class design.
The poem wrote: And as for noble metadata I'll have to sing its praises later Its uses are so numerous To give their due, I'd miss the bus
public class Test { @Somewhere public void someMethod() { ... } } The code will be generated by the @Somewhere annotation.
It is also called "Program Annotation."
Note that the metadata will not introduce any new language keyword. It makes clever use of existing "punctuation." To declare an annotation type:
public @interface Foo { ... }Here "@interface" means "annotation-type" (get it? a-t -> at -> @). Also, it looks like a javadoc tag.
To annotate:
@Copyright("Acme Inc") public static final int baz(...) { ... }
public void aMethod(String... args) { for(String s : args) { System.out.println(s); } } The aMethod can be called in the following ways: aMethod("here","we","go"); //3 argument list aMethod("to","be","or","not","to","be"); //6 argument list Note that the compiler will translate the aMethod automatically as: aMethod(new String[] {"here","we","go"}); aMethod(new String[] {"to","be","or","not","to","be"});
Quote start:
Tiger, Tiger Burning Bright Like a geek who works all night What new-fangled bit or byte Could ease the hacker's weary plight? To the most despised cast We'll bid a fond farewell at last With generics' burning spear The need for cast will disappear While Iterators have their uses They sometimes strangle us like nooses With enhanced-for's deadly ray Iterator's kept at bay When from collections ints are drawn Wrapper classes make us mourn When Tiger comes, we'll shed no tears We'll autobox them in the ears The int-enum will soon be gone like a foe we've known too long With typesafe-enum's mighty power Our foe will bother us no more And from the constant interface we shall inherit no disgrace With static import at our side, our joy will be unqualified And as for noble metadata I'll have to sing its praises later Its uses are so numerous To give their due, I'd miss the bus
Quote end.
Early Drafts Proposals for J2SE 5.0
Effective Java Programming Language Guide