Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
Java Puzzlers
OOP 2009
Optional Tirgul #2
Josh Bloch & Neal Gafter
http://www.javapuzzlers.com
http://video.google.com/videoplay?docid=9214177555401838409
What are puzzlers?
• Short Java programs
• They appear simple, but it is hard to guess
what the outcome of the program is:
– some do not compile
– some throw exception when executed
– some hang
– some print incorrect result
– some have varying or unpredictable output
Example: Oddity
public static boolean isOdd(int i) {
return i % 2 == 1;
}
Method result is:
1. true all the time
2. false all the time
3. true half the time, false half the time
4. true quarter of the times
Example: Oddity
public static boolean isOdd(int i) {
return i % 2 == 1;
}
Method result is:
1. true all the time
2. false all the time
3. true half the time, false half the time
4. true quarter of the times
Example: Oddity
public static boolean isOdd(int i) {
return i % 2 == 1;
}
Method result is:
true quarter of the times – half of integers are
negative, for all negative integers i % 2 returns -1,
therefore isOdd returns false. To fix the problem,
return i % 2 != 0
Time For A Change
public class Change {
public static void main(String args[]) {
System.out.println(2.00 - 1.10);
}
}
What is the outcome?
1. prints 0.9
2. prints 0.90
3. prints 0.9000000000000000
4. prints something else
In The Loop
public class InTheLoop {
public static final int END = Integer.MAX_VALUE;
public static final int START = END - 100;
public static void main(String[] args) {
int count = 0;
for (int i = START; i <= END; i++)
count++;
System.out.println(count); What is the outcome?
}
1. prints 100
}
2. prints 101
3. prints nothing
4. throws an exception
Real life bug
public class IdGenerator {
public synchronized long getNewAndReserve(int interval) {
long value;
if (low + interval >= MAX_VALUE) {
high = getNewHighValue();
low = 0;
}
value = getNewId(high, low);
low += interval;
return value;
}
}
A Strange Saga of Suspicious Sort
public class SuspiciousSort {
public static void main(…) {
Random rnd = new Random();
Integer[] arr = new Integer[100];
for (int i = 0; i < arr.length; i++)
arr[i] = rnd.nextInt();
Comparator<Integer> cmp = new Comparator<Integer>() {
public int compare( Integer i1, Integer i2) {
return i2 - i1;
}
What is the outcome?
};
1. arr is always entirely sorted
Arrays.sort(arr, cmp);
2. arr is usually entirely sorted
}
3. arr usually not entirely sorted
4. throws an exception
Real life bug
public class Node implements Comparable {
private long id;
…
public int compareTo(Object obj) {
if (obj instanceof Node) {
Node tmp = (Node) obj;
return (int)(id - tmp.id);
}
return -1;
}
What
is
the
outcome
}
of
new Node(12884902889L).compareTo(
new Node(4294968297L ) )
(1) 1 (2) 0 (3) -1 (4) other
News: nearly all binary searches and
merge-sorts are broken (2006)
int mid =(low + high) / 2;
The sum overflows to a negative value, and the
value stays negative when divided by two. This
bug can manifest itself for arrays whose length
(in elements) is 230 or greater (roughly a billion
elements).
http://googleresearch.blogspot.com/2006/06/e
xtra-extra-read-all-about-it-nearly.html
Null and Void
public class Null {
public static void greet() {
System.out.println("Hello world!");
}
public static void main(String[] args) {
((Null) null).greet();
}
}
What is the outcome?
1.
2.
3.
4.
Prints “Hello World”
Does not compile
NullPointerException
Something else
Confusing constructor
public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] d) {
System.out.println(“Double array");
}
public static void main(…) {
What is the outcome?
new Confusing(null);
1. Object
}
2. Double array
}
3. Does not compile
4. NullPointerException
What’s The Point
class Point {
protected final int x, y;
private final String name;
public Point(int x, int y) { this.x = x; this.y = y; name = makeName(); }
protected String makeName() { return "[" + x + "," + y + "]"; }
public final String toString() { return name; }
}
public class ColorPoint extends Point {
private final String color;
public ColorPoint(int x, int y, String color) { super(x, y); this.color = color; }
protected String makeName() { return super.makeName() + ":" + color; }
public static void main(String[] args) {
System.out.println(new ColorPoint(4, 2, "purple"));
}
}
What is the outcome?
1. [4,2]:purple
2. [4,2]
3. Something else
Indecision
public class Indecisive {
public static void main(String[] args) {
System.out.println(decision());
}
static boolean decision() {
try {
return true;
What is the outcome?
} finally {
return false;
1. prints true
}
}
3. does not compile
}
2. prints false
4. throws an exception
Hello, Goodbye
public class HelloGoodbye {
public static void main(String[] args) {
try {
System.out.println("Hello world");
System.exit(0);
} finally {
System.out.println("Goodbye world");
}
}
}
1. Hello world
What is the outcome?
2. Hello world
Goodbye world
Shades of Gray
class C {
String Z = "White";
1. Prints “Black”
}
2. Prints “White”
class X {
static class Y {
3. Does not compile
static String Z = "Black"; 4. Something else
}
static C Y = new C();
}
public class ShadesOfGray {
public static void main(String[] args){
System.out.println(X.Y.Z);
}
}
What is the outcome?
It’s Absurd, It’s a Pain,
It’s a Super-class
public class Outer {
class Inner1 extends Outer {}
class Inner2 extends Inner1 {}
}
Why doesn’t it compile?
It’s Absurd, It’s a Pain,
It’s a Super-class
public class Outer {
class Inner1 extends Outer {
public Inner1() {
super(); //invokes Object() constructor
}
}
class Inner2 extends Inner1 {
public Inner2() {
super(); //invokes Inner1() constructor
}
}
}
It’s Absurd, It’s a Pain,
It’s a Super-class
public class Outer {
class Inner1 extends Outer {
public Inner1() {
super();
}
}
class Inner2 extends Inner1 {
public Inner2() {
this.super();
}
}
}
Outer
Inner1
Inner2
It’s Absurd, It’s a Pain,
It’s a Super-class
public class Outer {
class Inner1 extends Outer {
public Inner1() {
super();
}
}
class Inner2 extends Inner1 {
public Inner2() {
Outer.this.super();
}
}
}
It’s Absurd, It’s a Pain,
It’s a Super-class
More on that:
• Scope ambiguities between outer and super
• On the Interaction of Method Lookup and
Scope with Inheritance and Nesting (pdf)
The Moral
• Careful design is great.
• Testing is great.
• Formal methods are great.
• Code reviews are great.
• Static analysis is great.
But none of these things alone are sufficient to
eliminate bugs: they will always be with us.
We must program carefully, defensively, and
remain ever vigilant.
Josh Bloch