114

I was reading an InfoWorld article (link to Wayback machine since the excerpt was since removed), and came across this little tidbit:

Take the latest version of Java, which tries to make null-pointer checking easier by offering shorthand syntax for the endless pointer testing. Just adding a question mark to each method invocation automatically includes a test for null pointers, replacing a rat's nest of if-then statements, such as:

public String getPostcode(Person person) {
String ans= null;
if (person != null) {
Name nm= person.getName();
if (nm!= null) {
ans= nm.getPostcode();
}
}
return ans
} 

With this:

public String getFirstName(Person person) {
return person?.getName()?.getGivenName();
} 

I've scoured the internet (okay, I spent at least 15 minutes googling variations on "java question mark") and got nothing. So, my question: is there any official documentation on this? I found that C# has a similar operator (the "??" operator), but I'd like to get the documentation for the language I'm working in. Or, is this just a use of the ternary operator that I've never seen before.

Thanks!

Erty Seidohl
  • 4,487
  • 3
  • 33
  • 45
  • 3
    Could we have a link to the article at least? – Karl Knechtel Dec 08 '10 at 17:03
  • 1
    And the source of the snippet? – khachik Dec 08 '10 at 17:05
  • 5
    The article is wrong. http://infoworld.com/print/145292 I believe a Project Coin submission was submitted for it. But it wasn't selected (for reasons mentioned in the article - if you want to do that sort of thing, use C# or something), and certainly isn't in the current version of the Java language. – Tom Hawtin - tackline Dec 08 '10 at 17:05
  • 4
    That's not the same as the C# ?? operator: ?? coalesces nulls, i.e. `A ?? B == (A != null) ? A : B`. This appears to evaluate a property on an object if the object reference is not null, i.e. `A?.B == (A != null) ? A.B : null`. – Rup Dec 08 '10 at 17:07
  • 1
    @Erty: as a huge user of the @NotNull annotation, which is basically everywhere in the code I write, I don't know very well anymore what NPEs are (except when using badly desing APIs). Yet I find this "shortcut notation" cute and interesting. Of course the article is right when it states: *After all, it doesn't eliminate the root of the problem: the proliferation of null values due to fast and loose programming.* 'null' doesn't exist at the OOA/OOD level. It's another Java-idiosynchratic nonsense that can mostly be worked around. To me it's *@NotNull* everywhere. – SyntaxT3rr0r Dec 08 '10 at 17:08
  • Jon Skeet was quick to retract his answer...I wonder why! hmmmm.... – Buhake Sindi Dec 08 '10 at 17:09
  • @Karl, khachik: I linked to the article. Thanks for the reminder. – Erty Seidohl Dec 08 '10 at 17:10
  • PHP added something like this. – Marcus Adams Dec 08 '10 at 17:20
  • +1 @Webinator for @NotNull annotation (lol - is there a user NotNull? - they must hate (or love!) the NotNull annotation triggering their inbox). – Bert F Dec 09 '10 at 19:20
  • @Rup No, in C#, `??` is a null coalescing operator where as `?` (the "ternary conditional operator") provides quick null checking inline, as OP indicates. – Josh M. May 09 '18 at 12:42
  • @JoshM. OP is asking about `?.` which is the the [null conditional operator](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operators), not just `?`, and it didn't, AFAIK, exist in C# when I wrote that back then. – Rup May 09 '18 at 12:46
  • @Rup -- yep, I indicated the wrong name for the operator, my mistake, I was referring to `?` as in `thing?.Blah`. – Josh M. May 09 '18 at 16:49
  • This is one reason I love Ruby. `deep&.nested&.value` and `value = var1Null || thenVar2`. http://mitrev.net/ruby/2015/11/13/the-operator-in-ruby/ – Chloe Sep 30 '18 at 22:09

16 Answers16

97

The original idea comes from groovy. It was proposed for Java 7 as part of Project Coin: https://wiki.openjdk.java.net/display/Coin/2009+Proposals+TOC (Elvis and Other Null-Safe Operators), but hasn't been accepted yet.

The related Elvis operator ?: was proposed to make x ?: y shorthand for x != null ? x : y, especially useful when x is a complex expression.

Helder Pereira
  • 5,522
  • 2
  • 35
  • 52
ataylor
  • 64,891
  • 24
  • 161
  • 189
  • 5
    In java (where there's no auto-coercion to null) a shorthand for `x!=null ? x : y` – Michael Borgwardt Dec 08 '10 at 17:12
  • @Michael Borgwardt: good point, I was thinking of the groovy semantics. – ataylor Dec 08 '10 at 17:17
  • @Michael I figured it needed to be turned, but I still don't see it. How does a `:` work as a mouth? Is `?` supposed to represent an excessive volume of hair? – Karl Knechtel Dec 08 '10 at 17:27
  • 61
    `?` is Elvis Presley's signature quiff; the `:` just represents a pair of eyes as usual. Perhaps `?:-o` is more evocative... – Andrzej Doyle Dec 08 '10 at 17:34
  • @KarlKnechtel Turn it the other way, and the : are eyes, and the ? is a mouth/tongue. The expression is of a guy licking his lips. Appropriate for the "Elvis operator"? – Izkata Nov 11 '11 at 20:56
  • 4
    `?:0` Should be a "Not null, nor 0" operator. Make it so. – azz Apr 15 '13 at 08:55
  • 3
    It was actually a mistake to refer to the proposal as an Elvis operator. Explanation at http://mail.openjdk.java.net/pipermail/coin-dev/2009-July/002089.html "Null-safe dereferencing" is a better term to use. – JustinKSU Oct 17 '14 at 13:37
78

This syntax does not exist in Java, nor is it slated to be included in any of the upcoming versions that I know of.

ColinD
  • 108,630
  • 30
  • 201
  • 202
  • 10
    Why the downvote? This answer is 100% correct as far as I know... if you know something different, please say so. – ColinD Dec 08 '10 at 17:05
  • 2
    but obviously at one point it has been submitted (see Tom Hawtin's comments) and will maybe make it into the language. So a *"This syntax does not exist **yet** in Java"* would be more appropriate. – SyntaxT3rr0r Dec 08 '10 at 17:11
  • 6
    @Webinator: It's not going to be in Java 7 or 8, and there are no other "upcoming versions" at this time. I also find it kind of unlikely that it will make it in, since it encourages rather bad practices. I also don't think "yet" is necessary, since "does not exist in Java" is not the same as "will never exist in Java". – ColinD Dec 08 '10 at 17:12
  • 9
    @Webinator: several posters have commented that a proposal was submitted but rejected. Thus the answer is 100% accurate. Upvoting to counteract the down vote. – JeremyP Dec 08 '10 at 17:16
  • 3
    @ColinD _bad practice_ is when you give up on this ugly code and decide to use `Optional` and `map` stuff. we are not hiding the problem if value is nullable which means it is expected to be null sometimes and you have to handle that. sometimes default values are perfectly reasonable and its not a bad practice. – M.kazem Akhgary Dec 14 '18 at 10:24
36

[EDIT]

Upon further thought, I figured out that it is actually possible to achieve the same only using standard Java 8 classes:

public String getFirstName(Person person) {
    return Optional.ofNullable(person)
        .map(Person::getName)
        .map(Name::getGivenName)
        .orElse(null);
}

In this case, it is even possible to choose a default value (like "<no first name>") instead of null by passing it as parameter of orElse.


[Original Answer]

One way to workaround the lack of "?" operator using Java 8 without the overhead of try-catch (which could also hide a NullPointerException originated elsewhere, as mentioned) is to create a class to "pipe" methods in a Java-8-Stream style.

public class Pipe<T> {
    private T object;

    private Pipe(T t) {
        object = t;
    }

    public static<T> Pipe<T> of(T t) {
        return new Pipe<>(t);
    }

    public <S> Pipe<S> after(Function<? super T, ? extends S> plumber) {
        return new Pipe<>(object == null ? null : plumber.apply(object));
    }

    public T get() {
        return object;
    }

    public T orElse(T other) {
        return object == null ? other : object;
    }
}

Then, the given example would become:

public String getFirstName(Person person) {
    return Pipe.of(person)
        .after(Person::getName)
        .after(Name::getGivenName)
        .get();
}
Helder Pereira
  • 5,522
  • 2
  • 35
  • 52
25

Java does not have the exact syntax but as of JDK-8, we have the Optional API with various methods at our disposal. So, the C# version with the use of null conditional operator:

return person?.getName()?.getGivenName(); 

can be written as follows in Java with the Optional API:

 return Optional.ofNullable(person)
                .map(e -> e.getName())
                .map(e -> e.getGivenName())
                .orElse(null);

if any of person, getName or getGivenName is null then null is returned.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
  • 2
    An impressive example of boilerplate code needed if such operators are not available ~ 41 vs 97 chars. – Tom Mar 23 '23 at 10:27
20

There was a proposal for it in Java 7, but it was rejected:

http://tech.puredanger.com/java7/#null

pauljwilliams
  • 19,079
  • 3
  • 51
  • 79
8

That's actually Groovy's safe-dereference operator. You can't use it in pure Java (sadly), so that post is simply wrong (or more likely slightly misleading, if it's claiming Groovy to be the "latest version of Java").

Helder Pereira
  • 5,522
  • 2
  • 35
  • 52
Andrzej Doyle
  • 102,507
  • 33
  • 189
  • 228
7

See: https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (specifically "Elvis and other null safe operators").

The result is that this feature was considered for Java 7, but was not included.

Helder Pereira
  • 5,522
  • 2
  • 35
  • 52
Darron
  • 21,309
  • 5
  • 49
  • 53
3

As lot of answers mentioned Java language don't have this feature.

It is possible in few scenarios with this compiler plugin, with few limitations

In the example code you mentioned can be written as

public String getFirstName(Person person) {
  @NullSafe
  String retVal = person.getName().getGivenName();
  return retVal;
} 

PS: I am author of plugin

Vinay Lodha
  • 2,185
  • 20
  • 29
2

It is possible to define util methods which solves this in an almost pretty way with Java 8 lambda.

This is a variation of H-MANs solution but it uses overloaded methods with multiple arguments to handle multiple steps instead of catching NullPointerException.

Even if I think this solution is kind of cool I think I prefer Helder Pereira's seconds one since that doesn't require any util methods.

void example() {
    Entry entry = new Entry();
    // This is the same as H-MANs solution 
    Person person = getNullsafe(entry, e -> e.getPerson());    
    // Get object in several steps
    String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
    // Call void methods
    doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());        
}

/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
    if (o1 != null) return f1.apply(o1);
    return null; 
}

public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
    return getNullsafe(getNullsafe(o0, f1), f2);
}

public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
    return getNullsafe(getNullsafe(o0, f1, f2), f3);
}


/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
    if (o1 != null) f1.accept(o1);
}

public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
    doNullsafe(getNullsafe(o0, f1), f2);
}

public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
    doNullsafe(getNullsafe(o0, f1, f2), f3);
}


class Entry {
    Person getPerson() { return null; }
}

class Person {
    Name getName() { return null; }
}

class Name {
    void nameIt() {}
    String getGivenName() { return null; }
}
Lii
  • 11,553
  • 8
  • 64
  • 88
1

I'm not sure this would even work; if, say, the person reference was null, what would the runtime replace it with? A new Person? That would require the Person to have some default initialization that you'd expect in this case. You may avoid null reference exceptions but you'd still get unpredictable behavior if you didn't plan for these types of setups.

The ?? operator in C# might be best termed the "coalesce" operator; you can chain several expressions and it will return the first that isn't null. Unfortunately, Java doesn't have it. I think the best you could do is use the ternary operator to perform null checks and evaluate an alternative to the entire expression if any member in the chain is null:

return person == null ? "" 
    : person.getName() == null ? "" 
        : person.getName().getGivenName();

You could also use try-catch:

try
{
   return person.getName().getGivenName();
}
catch(NullReferenceException)
{
   return "";
}
KeithS
  • 70,210
  • 21
  • 112
  • 164
  • 1
    "what would the runtime replace it with?" ... reading the question might help :-P It would replace it with null. In general, the idea seems to be that person?.getName evaluates to null if person is null or to person.getName if not. So it's pretty much like replacing "" with null in all your examples. – subsub Feb 04 '13 at 15:35
  • 1
    A NullReferenceException could also been thrown in `getName()` or `getGivenName()` which you won't know if you simply return an empty string for all occurrences. – Jimmy T. Dec 14 '13 at 23:32
  • 1
    In Java it is NullPointerException. – Tuupertunut Mar 23 '17 at 12:51
  • in C#, `person?.getName()?.getGivenName() ?? ""` is the equivalent of your first example, with the exception that if `getGivenName()` returns null, it will still give `""` – Austin_Anderson Sep 13 '17 at 17:41
0

There you have it, null-safe invocation in Java 8:

public void someMethod() {
    String userName = nullIfAbsent(new Order(), t -> t.getAccount().getUser()
        .getName());
}

static <T, R> R nullIfAbsent(T t, Function<T, R> funct) {
    try {
        return funct.apply(t);
    } catch (NullPointerException e) {
        return null;
    }
}
H-MAN
  • 25
  • 1
  • I will have to try this. SI have serious doubts about this whole "Optional" business. Seems like a nasty hack. – ggb667 Jun 05 '14 at 17:49
  • 4
    The whole purpose of the Elvis Operator proposal was to do this in one line. This approach is no better than the "if(!=null) approach above. In fact I would argue it is worse as it is not a straight forward. Additionally you should avoid throwing and catching errors due to the overhead. – JustinKSU Oct 17 '14 at 13:22
  • 2
    As @Darron said in another answer, the same applies here: "The problem with this style is that the NullPointerException may not have come from where you expected it to. And thus it may hide a real bug." – Helder Pereira Aug 03 '15 at 22:50
0

If someone is looking for an alternative for old java versions, you can try this one I wrote:

/**
 * Strong typed Lambda to return NULL or DEFAULT VALUES instead of runtime errors. 
 * if you override the defaultValue method, if the execution result was null it will be used in place
 * 
 * 
 * Sample:
 * 
 * It won't throw a NullPointerException but null.
 * <pre>
 * {@code
 *  new RuntimeExceptionHandlerLambda<String> () {
 *      @Override
 *      public String evaluate() {
 *          String x = null;
 *          return x.trim();
 *      }  
 *  }.get();
 * }
 * <pre>
 * 
 * 
 * @author Robson_Farias
 *
 */

public abstract class RuntimeExceptionHandlerLambda<T> {

    private T result;

    private RuntimeException exception;

    public abstract T evaluate();

    public RuntimeException getException() {
        return exception;
    }

    public boolean hasException() {
        return exception != null;
    }

    public T defaultValue() {
        return result;
    }

    public T get() {
        try {
            result = evaluate();
        } catch (RuntimeException runtimeException) {
            exception = runtimeException;
        }
        return result == null ? defaultValue() : result;
    }

}
irobson
  • 825
  • 8
  • 20
0

You can test the code which you have provided and it will give syntax error.So, it is not supported in Java. Groovy does support it and it was proposed for Java 7 (but never got included).

However, you can use the Optional provided in Java 8. This might help you in achieving something on similar line. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

Example Code for Optional

SK -
  • 459
  • 5
  • 15
0

STEP-1 : Use this generic method.

public static <T> Optional<T> optionalChaining(Supplier<T> resolver) {
    try {
        T result = resolver.get();
        return Optional.ofNullable(result);
    } catch (NullPointerException e) {
        return Optional.empty();
    }
}

STEP-2 one example of usage of this method is below

Optional<String> rs = optionalChaining(()-> user.getName("Talha").getLastName());

if(rs.isPresent()) {
                    
}

Done !!

Mohsin Ejaz
  • 316
  • 3
  • 7
-2

Since Android does not support Lambda Functions unless your installed OS is >= 24, we need to use reflection.

// Example using doIt function with sample classes
public void Test() {
    testEntry(new Entry(null));
    testEntry(new Entry(new Person(new Name("Bob"))));
}

static void testEntry(Entry entry) {
    doIt(doIt(doIt(entry,  "getPerson"), "getName"), "getName");
}

// Helper to safely execute function 
public static <T,R> R doIt(T obj, String methodName) {
    try {
       if (obj != null) 
           return (R)obj.getClass().getDeclaredMethod(methodName).invoke(obj);
    } catch (Exception ignore) {
    }
    return null;
}
// Sample test classes
    static class Entry {
        Person person;
        Entry(Person person) { this.person = person; }
        Person getPerson() { return person; }
    }

    static class Person {
        Name name;
        Person(Name name) { this.name = name; }
        Name getName() { return name; }
    }

    static class Name {
        String name;
        Name(String name) { this.name = name; }
        String getName() {
            System.out.print(" Name:" + name + " ");
            return name;
        }
    }
}
LanDenLabs
  • 1,566
  • 16
  • 10
-4

If this is not a performance issue for you, you can write

public String getFirstName(Person person) {
  try {
     return person.getName().getGivenName();
  } catch (NullPointerException ignored) {
     return null;
  }
} 
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 8
    The problem with this style is that the NullPointerException may not have come from where you expected it to. And thus it may hide a real bug. – Darron Dec 08 '10 at 18:25
  • 2
    @Darron, Can you give an example of a getter you have written which could throw an NPE and how you would want to handle it differently? – Peter Lawrey Dec 08 '10 at 20:29
  • 2
    you run it into a separate variable and test it with an if as normal. The idea behind this operator is to eliminate that uglyness. Darron is right, your solution might hide and throw away exceptions you want to throw. Such as if `getName()` threw an exception internally that you do not want to throw away. – Mike Miller Dec 09 '10 at 19:27
  • 2
    Not any exception, it would have to be a NullPointerException. You are trying to protect yourself from a situation you haven't begun to explain how it might occur in a real application. – Peter Lawrey Dec 10 '10 at 09:36
  • 1
    In a real application `Person` could be a proxy accessing a DB or some non-heap memory and there could be a bug somewhere... Not very realistic, but, Peter, I'd bet you've never written a piece of code like above. – maaartinus Apr 16 '14 at 13:15