11

Imagine the following scenario Long critId = Long.valueOf(criteriaIdentifier);

If the view is initially loaded criteriaIdentifier may be null, afterwards I set the value depending of the selectedItem in the JSF View.

However, Long.valueOf(criteriaIdentifier) throws a NumberFormatException - If the string cannot be parsed as a long(i.e null).

I've thought of default setting the Id to default -1, but I wanted to know if there is better practice .

PS: technically the criteriaIdentifier can't be -1, since these values are set from the Database, with a Sequence Generator, so I should know -1 was the default value and properly do the default operations

0x45
  • 779
  • 3
  • 7
  • 26
  • `NumberFormatException` - If the string cannot be parsed as a long. Editted – 0x45 Apr 18 '18 at 08:23
  • If `null` is an expected value in some cases, perform a null check in before or sourround with try/catch – André Stannek Apr 18 '18 at 08:24
  • @AndréStannek it should be never NULL, and if it was, i perform a default action – 0x45 Apr 18 '18 at 08:26
  • Possible duplicate of [How to check if a String is numeric in Java](https://stackoverflow.com/questions/1102891/how-to-check-if-a-string-is-numeric-in-java) – Balázs Németh Apr 18 '18 at 08:26
  • Possible duplicate of [How to check a string contains only digits and decimal points?](https://stackoverflow.com/questions/24833364/how-to-check-a-string-contains-only-digits-and-decimal-points) – Shubhendu Pramanik Apr 18 '18 at 08:28
  • All the duplicate flags, did you even read my problem? – 0x45 Apr 18 '18 at 08:33

5 Answers5

14

You can use the NumberUtils from Apache Commons. It's null-safe and you can optionally specify a default value.

Example:

NumberUtils.toLong(null) = 0L
NumberUtils.toLong("")   = 0L
NumberUtils.toLong("1")  = 1L

NumberUtils.toLong(null, 1L) = 1L
NumberUtils.toLong("", 1L)   = 1L
NumberUtils.toLong("1", 0L)  = 1L

For more info, check the API.

Jacob van Lingen
  • 8,989
  • 7
  • 48
  • 78
Ehler
  • 285
  • 3
  • 11
6

When we say nullSafe we usually expect to receive a null from the API when passing null to it, not a 0 or -1 or any other value.

The intention is that the API does not break in case of receiving null, but simply returning null.

For this, use createLong static method of the org.apache.commons.lang3.math.NumberUtils.

CAUSION*: This throws NumberFormatException if the input String is NOT null and is NOT numeric.

CAUSION**: since 3.1 it handles hex (0Xhhhh) and octal (0ddd) notations. N.B. a leading zero means octal; spaces are not trimmed.

Sample:

NumberUtils.createLong(null) --> null
NumberUtils.createLong("1") --> 1
NumberUtils.createLong("hi") --> NumberFormatException
NumberUtils.createLong(" 11") --> NumberFormatException (does not trim)
NumberUtils.createLong("023") --> 19 (leading 0 means octal)
NumberUtils.createLong("0x23") --> 35 (leading 0x means hex)
msd.salehi
  • 839
  • 8
  • 14
5

Long.valueOf(null) will throw NumberFormatException, not NullPointerException.

In Java 8, you have the possibility to declaratively choose a default evaluation for a nullable inline, e.g.

Long.valueOf(
    Optional.ofNullable(criteriaIdentifier).orElseGet(() -> "-1")
)

It's a little verbose, but will allow you to default to -1l if criteriaIdentifier is null (no need for additional dependencies).

API here and here.

Mena
  • 47,782
  • 11
  • 87
  • 106
  • is there a Java 7 solution to this too? – 0x45 Apr 18 '18 at 08:34
  • @0x45 unfortunately no, there isn't as such. `Optional` comes with Java 8. You can either build your own util or use external libraries (or just check for `null` explicitly and assigning a value). – Mena Apr 18 '18 at 08:35
  • 1
    You shouldn't use Optional this way, just use a ternary expression, or do an explicit null check using an if. – Mark Rotteveel Apr 19 '18 at 17:17
2

I'm assuming criteriaIdentifier is a String. You could use org.apache.commons.lang3.math.NumberUtils.toLong(String, long) which gives you the default value if the String argument is null. Or you use org.apache.commons.lang3.math.NumberUtils.toLong(String) which returns zero if the String is null.

Yeti
  • 1,108
  • 19
  • 28
1

It depends on your scenario but usually there are ways to avoid such problems.

Generally setting IDs to -1 is a common practice but I don't think it is a good one. You know that -1 is not a possible value in your scenario but considering just the type Long it is a valid value. So everywhere in the code you will need to implement tests like if id!=-1 which makes the code harder to understand and generally the null value is more suitable for that scenario - Long object without a value.

If it was up to me for example in the method that receives an ID and waits a valid ID if I get null I would throw an exception and let the caller of the method handle that. If it is a web API for example (otherwise why would you get a String?) then you can throw an HTTP error. Or if you want to handle bad arguments then you better return null or use null as default value.

Veselin Davidov
  • 7,031
  • 1
  • 15
  • 23