Session 2500 PROGRAMMING PUZZLERSJoshua Bloch, Sr. Staff EngineerNeal Gafter, Staff EngineerSun Microsystems, Java SoftwareSession 2500 2IntroductionTen Java™ programming language puzzlesShort program with curious behaviorWhat does it print? (multiple choice)The mystery revealedHow to fix the problemThe moralCovers language and core librariesSession 2500 31. “All I Get Is Static”class Dog { public static void bark() { System.out.print("woof "); }}class Basenji extends Dog { public static void bark() { }}public class Bark { public static void main(String args[]) { Dog woofer = new Dog(); Dog nipper = new Basenji(); woofer.bark(); nipper.bark(); }}Session 2500 4What Does It Print?(a) woof(b) woof woof(c) It variesSession 2500 5What Does It Print?(a) woof(b) woof woof(c) It variesNo dynamic dispatch on static methodsSession 2500 6Another Lookclass Dog { public static void bark() { System.out.print("woof "); }}class Basenji extends Dog { public static void bark() { }}public class Bark { public static void main(String args[]) { Dog woofer = new Dog(); Dog nipper = new Basenji(); woofer.bark(); nipper.bark(); }}Session 2500 7How Do You Fix It?Remove static from the bark methodSession 2500 8The MoralStatic methods can’t be overriddenThey can only be hiddenDon’t hide static methodsNever invoke static methods on instancesNot instance.staticMethod()But Class.staticMethod()Session 2500 92. “What’s in a Name?”public class Name { private String first, last; public Name(String first, String last) { this.first = first; this.last = last; } public boolean equals(Object o) { if (!(o instanceof Name)) return false; Name n = (Name)o; return n.first.equals(first) && n.last.equals(last); } public static void main(String[] args) { Set s = new HashSet(); s.add(new Name("Donald", "Duck")); System.out.println( s.contains(new Name("Donald", "Duck"))); }}Session 2500 10What Does It Print?(a) true(b) false(c) It variesSession 2500 11What Does It Print?(a) true(b) false(c) It variesDonald is in the set, but the set can’t find himThe Name class violates the hashCode contractSession 2500 12Another Lookpublic class Name { private String first, last; public Name(String first, String last) { this.first = first; this.last = last; } public boolean equals(Object o) { if (!(o instanceof Name)) return false; Name n = (Name)o; return n.first.equals(first) && n.last.equals(last); } public static void main(String[] args) { Set s = new HashSet(); s.add(new Name("Donald", "Duck")); System.out.println( s.contains(new Name("Donald", "Duck"))); }}Session 2500 13How Do You Fix It?Add a hashCode method:public int hashCode() { return 31 * first.hashCode() + last.hashCode();}Session 2500 14The MoralOverride hashCode when overriding equalsObey general contracts when overridingSee Effective JavaTM, Chapter 3Session 2500 153. “Indecision”class Indecisive { public static void main(String[] args) { System.out.println(waffle()); } static boolean waffle() { try { return true; } finally { return false; } }}Session 2500 16What Does It Print?(a) true(b) false(c) None of the aboveSession 2500 17What Does It Print?(a) true(b) false(c) None of the aboveThe finally is processed after the try.Session 2500 18Another Lookclass Indecisive { public static void main(String[] args) { System.out.println(waffle()); } static boolean waffle() { try { return true; } finally { return false; } }}Session 2500 19The MoralAvoid abrupt completion of finally blocksWrap unpredictable actions with nested trysDon’t return or throw exceptionsSession 2500 204. “The Saga of the Sordid Sort”public class SordidSort { public static void main(String args[]) { Integer big = new Integer( 2000000000); Integer small = new Integer(-2000000000); Integer zero = new Integer(0); Integer[] arr = new Integer[] {big, small, zero}; Arrays.sort(arr, new Comparator() { public int compare(Object o1, Object o2) { return ((Integer)o2).intValue() - ((Integer)o1).intValue(); } }); System.out.println(Arrays.asList(arr)); }}Session 2500 21What Does It Print?(a) [-2000000000, 0, 2000000000](b) [2000000000, 0, -2000000000](c) [-2000000000, 2000000000, 0](d) It variesSession 2500 22What Does It Print?(a) [-2000000000, 0, 2000000000](b) [2000000000, 0, -2000000000](c) [-2000000000, 2000000000, 0](d) It varies (behavior is undefined)The comparator is broken!It relies on int subtractionint too small to hold difference of 2 arbitrary intsSession 2500 23Another Lookpublic class SordidSort { public static void main(String args[]) { Integer big = new Integer( 2000000000); Integer small = new Integer(-2000000000); Integer zero = new Integer(0); Integer[] arr = new Integer[] {big, small, zero}; Arrays.sort(arr, new Comparator() { public int compare(Object o1, Object o2) { return ((Integer)o2).intValue() - ((Integer)o1).intValue(); } }); System.out.println(Arrays.asList(arr)); }}Session 2500 24How Do You Fix It?Replace comparator with one that works public int compare(Object o1, Object o2) { int i1 = ((Integer)o1).intValue(); int i2 = ((Integer)o2).intValue(); return (i2 < i1 ? -1 : (i2 == i1 ? 0 : 1)); }Session 2500 25The Moralints aren’t integers!Think about overflowThis particular comparison techniqueOK only if max - min <= Integer.MAX_VALUEFor example: all values positiveDon’t write overly clever codeSession 2500 265. “You’re Such a Character”public class Trivial { public static void main(String args[]) { System.out.print("H" + "a"); System.out.print('H' + 'a'); }}Session 2500 27What Does It Print?(a) HaHa(b) Ha(c) None of the aboveSession 2500 28What Does It Print?(a) HaHa(b) Ha(c) None of the above: It prints Ha169'H' + 'a' evaluated as int, then converted to String. Ouch.Session 2500 29The
View Full Document