FULL PRODUCT VERSION : java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b18) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 6.3.9600] EXTRA RELEVANT SYSTEM CONFIGURATION : I am using: Eclipse Java EE IDE for Web Developers. Version: Luna Service Release 2 (4.4.2) Build id: 20150219-0600 A DESCRIPTION OF THE PROBLEM : I have a method called toInteger to parse a string to a Integer. It receives two arguments, the string to parse and a replacement if the string cannot be parsed. The arguments are: value : String, replace : Integer the body method: return value == null ? replace : isInteger(value) ? Integer.parseInt(value) : replace; *the method isInteger receives string : String, and returns boolean: return string != null && string.matches("-?\\d+"); I call toInteger passing a string and a null as a replacement. In case that the string value is null, it has to return the null replacement, and in case the string value is not null nor a numeric string, it has to return the null replacement too. In any of that two cases it doesn't performs the Integer.parseInt method. But the call to toInteger with a null replacement throws a NullPointerException (not a NumberFormatException). That is curious is that if I encapsulate the Integer.parseint to an another method, in my case called parseInt, the toInteger returns the null replacement without throwing the NullPointerException. I have tried with a shorter expression without nesting conditional operators, and well, a better expression: return value == null && isInteger(value) ? parseInt(value) : replace; That returns the null replacement without the NullPointerException. I think the bug is nesting conditional operators. STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : Executing the attached source code is sufficient, is a short source. EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - When I pass a unparseable string as a first argument, and a null replacement as a second argument, I expected the toInteger method to return null. ACTUAL - The actual result for the toInteger method is a NullPointerException, but returns the expected null when calling the methods toInteger2, that encapsulates de Integer.parseInt, toInteger3 and toInteger4, that both avoids nested conditional operators., REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- package main; public class Main { public static void main(String[] args) { ints(); } public static void ints() { try { Integer i = toInteger(null, null); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } try { Integer i = toInteger2(null, null); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } try { Integer i = toInteger3(null, null); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } try { Integer i = toInteger4(null, null); System.out.println(i); } catch (Exception e) { e.printStackTrace(); } } public static Integer toInteger(final String value, final Integer replace) { //NullPointerException if replace is null return value == null ? replace : isInteger(value) ? Integer.parseInt(value) : replace; } public static Integer toInteger2(final String value, final Integer replace) { //Encapsulates Integer.parseInt with parseInt return value == null ? replace : isInteger(value) ? parseInt(value) : replace; } public static Integer toInteger3(final String value, final Integer replace) { return value == null && isInteger(value) ? parseInt(value) : replace; } public static Integer toInteger4(final String value, final Integer replace) { if (value != null && isInteger(value)) { return Integer.parseInt(value); } else { return replace; } } public static boolean isInteger(final String string) { return string != null && string.matches("-?\\d+"); } public static Integer parseInt(final String value) { return Integer.parseInt(value); } } ---------- END SOURCE ----------
|