Express killers, part III
In this part we will consider how JVM takes care of reference printing, that are pointing to nowhere, it means null
. There is short code sample that prints class name of the object received from collection:
import java.util.ArrayList; import java.util.List; public class PrintNull { private static PrintNull o; public static void main(String[] args) { List<PrintNull> list = new ArrayList<PrintNull>(); list.add(o); for (PrintNull i : list) { System.out.println(i.toString()); } } public String toString() { return (this == null) ? "<null>" : super.toString(); } }
What will be printed?
- null
- <null>
- different value every time
- none of above
Very short sample and question: what is it doing? Anything at all? Is it result of "refactoring by removing"?
synchronized(obj) { }
Answers:
First example:
Null was added to collection, so it will be taken in loop. Try to call method on the null object will result in throwing exception. It will be safer to use System.err.println(i)
instead, what will print "null". Overwritting toString()
method is useless. Also check if this is equal to null
is pointless (when is it true
?).
Second example:
I found that code once in repository. We were discussing together if it is done by purpose or maybe it is side effect of some refactoring and code removal. At first sight this code is useless, because there is nothing inside. However, if you look closer, we might find potential usage. There is sample usage. Check what will be printed with and without this block in printTrue()
method.
public class Sync implements Runnable { private static final Object obj = new Object(); private final boolean id; public Sync(boolean id) { this.id = id; } public static void main(String[] args) { new Thread(new Sync(false)).start(); } public void run() { System.err.println("start:" + id); if (id) { printTrue(); } else { printFalse(); } System.err.println("end:" + id); } public void printTrue() { // remove that lines and check results synchronized (obj) { } } public synchronized void printFalse() { synchronized (obj) { try { new Thread(new Sync(true)).start(); wait(2000); System.err.println("print"); } catch (InterruptedException ex) { ex.printStackTrace(); } } } }
Calling wait(2000)
is done only for purpose of this example, and execution may be different (however 2 secs should be enough to see difference). To sum up, code is weird, however removing it may cause with some new bugs to fix.
Translation: Grzegorz Duda
Nobody has commented it yet.