Community
Participate
Working Groups
Expression evaluation should occur from left to right, but when parentheses are added to the right hand side of an expression, the bytecode generated by the JDT dictates that the RHS evaluation is first. Consider the following java code: public class EvalTest { private static String n = null; public static void test1() { if (n == null || n.equals("") || true) System.out.println("null or \"\""); else System.out.println("other"); } public static void test2() { if (n == null || (n.equals("") || true)) // *** note - extra set of parentheses in this line System.out.println("null or \"\""); else System.out.println("other"); } public static void main(String[] args) { System.out.println("test1:"); test1(); System.out.println("test2:"); test2(); } } I would expect both of the above methods to evaluate the 'n == null' test first and since that evaluation returns true, they shouldn't evaluate the rest. If I compile the above class using JAVAC then it works that way (the bytecode for test1 and test2 are identical). If I compile it using the eclipse JDT then the bytecode for test1 is different to test2. The test2 bytecode evaluates the 'n.equals("")' test first, which generates a NullPointerException. Here's the bytecode produced by eclipse for the test1 and test2 methods: Method void test1() 0 getstatic #11 <Field java.lang.String n> 3 ifnull 15 6 getstatic #11 <Field java.lang.String n> 9 ldc #21 <String ""> 11 invokevirtual #27 <Method boolean equals(java.lang.Object)> 14 pop 15 getstatic #33 <Field java.io.PrintStream out> 18 ldc #35 <String "null or """> 20 invokevirtual #41 <Method void println(java.lang.String)> 23 return Method void test2() 0 getstatic #11 <Field java.lang.String n> 3 ldc #21 <String ""> 5 invokevirtual #27 <Method boolean equals(java.lang.Object)> 8 pop 9 getstatic #33 <Field java.io.PrintStream out> 12 ldc #35 <String "null or """> 14 invokevirtual #41 <Method void println(java.lang.String)> 17 return
Given Java is left associate, (n == null || n.equals("") || true) is strictly equivalent to ((n == null || n.equal("")) || true) however, I agree we have a bug, since in the end it shouldn't make a difference on this very example. The nuance however explains why we have this bug in this case (and in this case only).
Similar defect on: (n != null && (n.equal("")) && false)) Fix under testing.
Fixed (will release after 3.0M1 is declared)
Verified.