A utility method representing, "Both not null and not equal" in Java
Asked Answered
C

5

1
String str = "abc";

Comparing this string variable like the following.

if(str.equals("abc")) {}

In case str is null, it will cause a java.lang.NullPointerException to be thrown as obvious.

To avoid that, an additional null check may be enforced. Such as,

if(str != null && str.equals("abc")) {}

I find it plain ugly. Better could be rewritten as follows.

if("abc".equals(str)) {}

This will never throw a java.lang.NullPointerException even though str is null. Besides, object equals null is never true.


The last case however, cannot be used, when the conditional expression is inverted like so,

if(!"abc".equals(str)) {
    System.out.println(str.length());
}

This will cause a java.lang.NullPointerException inside the if block, if str is null.

Can this somehow be avoided without rewriting the conditional statement like the following?

if(str != null && !"abc".equals(str)) {}

This is plain ugly and unreadable.


Although the example uses a String object, it may be a more complex object.

Cacao answered 31/7, 2015 at 10:53 Comment(11)
You have to add a condition to the print statement : System.out.println(str != null ? str.length() : 0);Homochromous
write a static method which handles null silently...Ribaldry
if possible use apache commons StringUtils.isEmpty() that makes code readable as wellFrey
could you explain why you think condition (str != null && !"abc".equals(str)) is ugly?Starstarboard
@Starstarboard : Despite the fact that this is a toy example, the code will get uglier at long run in big applications, if there are so many such conditional checks.Cacao
Avoid str being null in the first place…Squadron
@Squadron : It is not always possible. For example, if there is a null foreign key in the database (ON DELETE SET NULL), a null check is unavoidable on the JPA/ORM side. I however, excluded that part from this question.Cacao
It still should be sorted out way before doing any string comparisons…Squadron
@Cacao if you have too many conditions you could create utility method to deal with them or disallow to use null, and use null object pattern insteadStarstarboard
I like commons-lang's StringUtils.isNotEmpty(string) method, personally. If you don't want to include the lib, you can just make your own.Explosive
@Explosive : I also use that library extensively :). Besides that I see, when objects to be compared are other than a String, an additional condition is always necessary such as if(object1 != null && object1.equals(object2)) {...}. (A client can supply a User object with optional field values of Country, State and City all three set to null in User. In this case, it is absolutely not the client's responsibility to fight against a null value. It is however, the upper service layer's responsibility to adequately handle a java.lang.NullPointerException whenever necessary).Cacao
C
1

Long story short : There is simply no library method doing this which I know of. This if(str != null && !"abc".equals(str)) {} actually requires that both the objects to be compared are not null and not equal to each other.

A static utility method performing this task is sufficient to deal with.

/**
 * Returns {@code true} if and only if both the arguments (objects) are
 * <b>not</b> {@code null} and are not equal to each other and {@code false}
 * otherwise.
 *
 * @param a an object.
 * @param b an object to be compared with {@code a} for equality.
 * @return {@code true} if both the arguments (objects) are <b>not</b> {@code null}
 * and not equal to each other.
 */
public static boolean notEquals(Object a, Object b) {
    return (a == b || a == null || b == null) ? false : !a.equals(b);
}
Cacao answered 1/8, 2015 at 12:42 Comment(0)
B
4

An alternative could be to use the Java 8 optional wrapper

Optional<Customer> optional = findCustomer();

if (optional.isPresent()) {
Customer customer = maybeCustomer.get();
    ... use customer ...
}
else {
    ... deal with absence case ...
}

source: https://dzone.com/articles/java-8-optional-how-use-it

Biotic answered 31/7, 2015 at 11:1 Comment(3)
Side note: if you are not yet on java 7, have a look at Guava's Optional.Rite
You should make your example closer to the use case of the question, e.g. Optional.ofNullable(oldAPIreturningNullable).filter(s -> !s.equals("abc)).ifPresent( s->intendedAction);Squadron
This is only helpful/useful, when developers inadvertently forget to do null checks. It also requires conditional checks. What is the benefit of doing this, Fruit fruit = new Fruit(); Optional<Fruit>optional = Optional.of(fruit); if(optional.isPresent()) {System.out.println("present");} than simply doing this if(fruit != null) {System.out.println("present");}? In both the cases, a test condition is required. Besides, Optional.of(fruit) itself throws a java.lang.NullPointerException, if fruit itself is null beforehand.Cacao
B
1

You have to check for null at some point if you want to use str. There is simply no way around it. You can wrap this check into a additional utility function or something like this, but in the end you will not get around the additional check.

If you are a friend of using loads of additional libraries you could use org.apache.commons.lang.StringUtils#length(java.lang.String). That does just what you want, maybe you got a library like that present in your application anyway. The apache one is only a example. There are surely others around that do similar things.

If you want to remove the null check all together maybe the better question is: Why can str be null and it is possible to prevent it being null by not accepting this value from the very beginning.

Burgin answered 31/7, 2015 at 11:7 Comment(0)
F
1

Another possible way to avoid nulls is using an assert: Look at this answer in another similar question:

How to check to see that a set of variables is not null before continuing

Feasible answered 31/7, 2015 at 12:14 Comment(0)
C
1

Long story short : There is simply no library method doing this which I know of. This if(str != null && !"abc".equals(str)) {} actually requires that both the objects to be compared are not null and not equal to each other.

A static utility method performing this task is sufficient to deal with.

/**
 * Returns {@code true} if and only if both the arguments (objects) are
 * <b>not</b> {@code null} and are not equal to each other and {@code false}
 * otherwise.
 *
 * @param a an object.
 * @param b an object to be compared with {@code a} for equality.
 * @return {@code true} if both the arguments (objects) are <b>not</b> {@code null}
 * and not equal to each other.
 */
public static boolean notEquals(Object a, Object b) {
    return (a == b || a == null || b == null) ? false : !a.equals(b);
}
Cacao answered 1/8, 2015 at 12:42 Comment(0)
C
0

I think u can use Stringutils from org.apache.commons.lang3.StringUtils;

@Test
public void Test() {
    String fakeParentId = null;
    if (!StringUtils.equals(fakeParentId, "-1")) {
        log.debug("it is not -1");
    }
}

and it returns it is not -1

Colleen answered 20/5 at 1:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.