3

I have an object myObject and I want to make sure that it is null or else I want to print a custom message with the object's id. I have the following line of code trying to achieve the same

Preconditions.checkArgument(Objects.isNull(myObject),
                        "This object is not null #%s.", myObject.getId());

This condition works fine when myObject is not null. It throws the appropriate exception message. But when the object is indeed null, it was my expectation that the rest of the code would be executed but instead, I get a null pointer exception because of myObject.getId() call.

Do guava preconditions evaluate the exception message string regardless of whether the condition is true or not?

Marco Polo
  • 113
  • 1
  • 6
  • 2
    this has nothing to do with `guava`, that is the error message that gets computed _either way_, not matter if it gets printed or not. You could write it as `... "This object is not null #%s.", myObject == null ? null: myObject.getId()` - since you do not really care about the message in that case – Eugene Mar 17 '20 at 14:06
  • As written in the Javadoc, don't use [`Objects.isNull`](https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/Objects.html#isNull(java.lang.Object)) other than in the context of method references, as in `.filter(Objects::isNull)`. Instead, use `Preconditions.checkArgument(myObject == null)`. – Olivier Grégoire Mar 17 '20 at 14:38
  • 1
    What's the advantage of the 3rd party library method over `if(myObject != null) throw new IllegalArgumentException("This object is not null #" + myObject.getId());`? I mean, besides obfuscating what's going on and leading to bugs like the one in the question? And why having this parameter at all, when it is supposed to be always `null`? – Holger Mar 17 '20 at 15:34

2 Answers2

5

With

Preconditions.checkArgument(Objects.isNull(myObject),
                    "This object is not null #%s.", myObject.getId());

you have to look what happens in which order:

Before any call to checkArgument() can occur, all arguments to it are evaluated:

  • Objects.isNull(myObject)
  • the string
  • myObject.getId()

Only then the call can occur, and if an exception occurs during this evaluation, the call doesn't happen at the first place.

Just for completeness, as it was already mentioned elsewhere: the way to go would be myObject == null ? null: myObject.getId(), as it avoids the dereferencing in the case of a null object.

glglgl
  • 89,107
  • 13
  • 149
  • 217
2

You could hack it via (for example):

static void test(Object myObject) {

    Preconditions.checkArgument(
        myObject == null, "This object is not null #%s.", myObject == null ? null : myObject.getId()
    );

}

The condition: myObject == null ? myObject : myObject.hashCode() is still going to be evaluated, always; but the error Message itself will not be computed until needed.

Eugene
  • 117,005
  • 15
  • 201
  • 306