I was reading an article linked from a slashdot story, 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!
EDIT: Link to the article: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292
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.
This syntax does not exist in Java, nor is it slated to be included in any of the upcoming versions that I know of.
[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();
}
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.
There was a proposal for it in Java 7, but it was rejected:
http://tech.puredanger.com/java7/#null
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.
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").
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
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; }
}
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 "";
}
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;
}
}
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;
}
}
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
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 !!
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;
}
}
}
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;
}
}
Related
I have a Java class like below
class MyClass {
public boolean rule1() {...}
public boolean rule2() {...}
public boolean rule3() {...}
}
now for instance I want to check the rule of above class in many ways such as :
MyClass myClass = new MyClass();
if (myClass.rule1() && myClass.rule2 || myClass.rule3) {}
and Now I am wondering that how can I implement above line with like this one?
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
The cleaner way would be to use the functional interface Predicate:
Type Parameters:
T - the type of the input to the predicate Functional
Interface: This is a functional interface and can therefore be used as
the assignment target for a lambda expression or method reference.
public class A {
public Predicate rule1() {
return //some operation that returns a boolean;
}
public Predicate rule2() {
return //some operation that returns a boolean;
}
public Predicate rule3() {
return //some operation that returns a boolean;
}
}
But the if chain of method calls would not look like you are looking for, namely:
if (myClass.rule1().and().rule2().or().rule3().accept()) {}
Otherwise, you would have to implement the Builder pattern, and implement the and(), or(), and accept methods. For instance:
public class BooleanEvaluator {
List<String> rules = new ArrayList<>();
public BooleanEvaluator and() {
rules.add("&&");
return this;
}
public BooleanEvaluator or() {
rules.add("or");
return this;
}
public boolean accept() {
int i = 0;
boolean result = Boolean.parseBoolean(rules.get(0));
while (i < rules.size() - 1) {
if(rules.get(i).equals("&&")){
result = result && Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
else if(rules.get(i).equals("||")){
result = result || Boolean.parseBoolean(rules.get(i + 1));
i+=2;
}
}
return false;
}
public BooleanEvaluator rule1() {
boolean result = // apply the rule 1
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule2() {
boolean result = // apply the rule 2
rules.add(String.valueOf(result));
return this;
}
public BooleanEvaluator rule3() {
boolean result = // apply the rule 3
rules.add(String.valueOf(result));
return this;
}
void some_method(){
if (this.rule1().and().rule2().or().rule3().accept()) {
// ...
}
}
}
Naturally, the accept method would have to be much more robust, this is just to show what would the design look like.
Have a look at Predicate<T> and its and or or.
MyClass instance = new MyClass();
Predicate<MyClass> predicate = MyClass::rule1;
if (predicate.and(MyClass::rule2).or(MyClass::rule3).test(instance)) {
// todo
}
It might look less readable than the version you mentioned, renaming MyClass to something more meaningful would help. If it doesn't work for you, consider writing a Builder. Good complex examples of which can be found in, let's say, dynamic SQL builders (for example, jooq).
Does anyone know any solution to safely get value without NPE and without a lot of if statements?
For example, we have: userInfo.getAddressInfo().getCityName(),
how to get cityName without null-checks?
Sometimes, for my pet projects I use something like that:
public static <T> String safeGetValue(Supplier<String> supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return "";
}
Maybe exists better way to do this.
Full example:
import java.util.function.Supplier;
public class ExampleClass {
public static void main(String[] args) {
UserInfoResponse userInfo = new UserInfoResponse();
String value = safeGetValue(() -> userInfo.getAddressInfo().getCityName());
System.out.println(value);
}
public static <T> String safeGetValue(Supplier<String> supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return "";
}
public static <T> String safeGetValue(Supplier<String> supplier, String defaultValue) {
try {
return supplier.get();
} catch (NullPointerException e) {
e.printStackTrace();
}
return defaultValue;
}
public static <T> String safeGetValue(Supplier<String> supplier, Runnable runnable) {
try {
return supplier.get();
} catch (NullPointerException e) {
runnable.run();
}
return "";
}
public static <T> String safeGetValue(Supplier<String> supplier, Runnable runnable, String defaultValue) {
try {
return supplier.get();
} catch (NullPointerException e) {
runnable.run();
}
return defaultValue;
}
}
class UserInfoResponse {
private String firstName;
private UserAddressInfo addressInfo;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public UserAddressInfo getAddressInfo() {
return addressInfo;
}
public void setAddressInfo(UserAddressInfo addressInfo) {
this.addressInfo = addressInfo;
}
}
class UserAddressInfo {
private String cityName;
public String getCityName() {
return cityName;
}
public void setCityName(String cityName) {
this.cityName = cityName;
}
}
I'm looking for a solution without if statements.
Ternary statement can't be a good solution too.
Unfortunately, if tests and conditional expressions are the only alternatives to catching NPEs. (But they are better alternatives!)
To me, the real problem is that the nulls are there in the first place. A better idea is to modify the design so that nulls are not returned. If they are not returned by getters, then you don't have to deal with them.
Here are some ways to design your APIs to not return null.
Make it impossible to create domain objects with null field values:
Constructors and setters should check that their arguments are not null, and thrown an exception (e.g. NPE) when called with bogus null arguments.
Fields could be default initialized with non-null values.
Have the getters return non-null values when field values are null. (But see below!)
Have the getters throw an exception when the user gets a field which should not be null has a null value.
Use the Null Object pattern. Create an special instance of each of your domain objects that represents "no object". Ideally, a Null Object should be immutable ... or should throw an exception if you attempt to modify it by accident.
Use Optional<ReferenceType>.
For builtin types / common types:
use "" instead of null for strings
use a zero length array instead of null for arrays
use (immutable) empty collection objects instead of null for collection types
avoid the primitive wrapper types: use the primitive types that cannot be null.
The other way to look at this is that if your API is specified so that a getter shouldn't return a null, then if it does return a null that is a bug. So, if you then write code to turn the nulls into something else (e.g. empty strings) to avoid the pesky NPEs, what you actually doing is hiding the bugs. A better idea is to let the NPE happen, log it, and then crash the application. (Or return a "500 Internal Error" response.)
Fixing a bug is better than hiding a bug.
But (I hear you ask) "What about reliability? It is embarrassing if my code crashes with NPEs!"
Well yes, but an NPE is better than a null workaround that gives incorrect answers to your users ... or writes bad data into your database.
And the conventional way to avoid bugs (e.g. NPEs) showing up in production is extensive automated testing. More / better unit tests. More / better system tests. Beta test releases, pre-production servers, etc.
Using Optional<T> chain you can write following
UserInfoResponse userInfo = new UserInfoResponse();
String value = Optional.ofNullable(userInfo.getAddressInfo())
.map(UserAddressInfo::getCityName)
.orElse(null);
or
String value = Optional.ofNullable(userInfo)
.map(UserInfoResponse::getAddressInfo)
.map(UserAddressInfo::getCityName)
.orElse(null);
or
String value = Optional.ofNullable(userInfo)
.map(ui -> ui.getAddressInfo())
.map(uai -> uai.getCityName())
.orElse(null);
I have seen someone creating a custom argument matcher like the following. However, I am having difficulty understanding how it works.
What I can understand its a method that takes a parameter and returns a ArgumentMatcher which is an interface that has a type of List<Person>. And the overriden method is the matcher that uses a lambda. I think the body part is the most confusing, if anyone can explain that.
private ArgumentMatcher<List<Person> personListSize(final int size) {
return argument -> argument.personList().size() == size;
}
This is the way I would normally do something like this, which to me is easier to understand, just wondering how can I get the following to look like the above?
public class CustomArgumentMatcher implements ArgumentMatcher<List<Person>> {
#Override
public boolean matches(List<Person> argument) {
return argument.size() == size;
}
}
Just starting to understand, this works:
private ArgumentMatcher<String> stringMatcher = new ArgumentMatcher<String>() {
#Override
public boolean matches(String argument) {
return argument.contains("");
}
};
However, If I add a parameter to pass in like this:
private ArgumentMatcher<String> stringMatcherArgs(final String name) = new ArgumentMatcher<String>() {
}
I get a error message saying unexpected token just wondering to pass in a parameter in the above?
You should read this document about Lambda Expressions
Here are your examples:
private ArgumentMatcher<List<Person>> customArgumentMatcher(final int size) {
return argument -> argument.size() == size;
}
private ArgumentMatcher<List<Person>> stringMatcherArgs(final String name) {
return argument -> argument.contains(name);
}
You got it all correct just connect the dots...
private ArgumentMatcher<List<Person> personListSize(final int size) {
return new ArgumentMatcher<List<Person>>() {
#Override
public boolean matches(List<Person> argument) {
return argument.size() == size;
}
};
}
and use it with argThat
Mockito.verify(mockClass).foo(argThat(personListSize(5));
If your still looking for the kotlin equivalent of Gustavo`s answer
(note that you should have created another question instead),
try the following:
fun customArgumentMatcher(size : Int) : ArgumentMatcher<List<Person>> {
return object : ArgumentMatcher<List<Person>> {
override fun matches(argument : List<Person>) = argument.size == size;
}
}
See also:
Setting anonymous interface in Kotlin
I have the following scenario: two validation Helpers
the StringValidationHelper ...
public class StringValidationHelper {
public static Validation<String> notNull =
SimpleValidation.from(s -> s != null, "must not be null.");
public static Validation<String> moreThan(int size) {
return SimpleValidation.from(
s -> s.length() >= size,
String.format ("must have more than %s chars.", size));
}
... // More methods (lessThan, etc)}
... and NumberValidationHelper.
public class NumberValidationHelper {
public static Validation<Number> notNull =
SimpleValidation.from(n -> n != null, "must not be null");
public static <N extends Number & Comparable<N>> Validation<N> lowerThan(N max){
return SimpleValidation.from(
n -> n.compareTo(max) == -1,
String.format("must be lower than %s.", max));
}
... // More methods like (greaterThan, etc)}
The method from is a static factory method that receives a Predicate and a message to eventual validation fails.
public class SimpleValidation<K> implements Validation<K>{
private Predicate<K> predicate;
private String onErrorMessage;
private SimpleValidation(Predicate<K> predicate, String onErrorMessage) {
this.predicate = predicate;
this.onErrorMessage = onErrorMessage;
}
public static <K> SimpleValidation<K> from(Predicate<K> predicate, String onErrorMessage){
return new SimpleValidation<>(predicate, onErrorMessage);
}
... // Omitted for simplicity
}
Thanks to the Validation interface, you can enjoy a wonderfully smooth interface
#FunctionalInterface
public interface Validation<K> {
... // Omitted for simplicity
default Validation<K> and(Validation<K> other) {
return param -> {
ValidationResult firstResult = this.test (param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
... // Omitted for simplicity
}
So I can start, for example, a validation using the closure notNull.
Example: with NumberValidationHelper
public class MyValidate {
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
}
This validation framework I developed based on this article.
Well, notNull enclaves a type-independent behavior, so I'd like to remove the duplication of these two helpers.
I'm not finding an obvious shape without losing the fluid interface.
Because the variable is static, you can not use generics and extend the behavior, for instance.
public abstract class GenericHelper<K> {
public static Validation<K> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
Also it does not bother me to type Validation with Object as below:
public abstract class GenericHelper {
public static Validation<Object> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
... because in the call chaining, it will give compilation error since the result of notNull will be a Validation< Object > and and will be expecting a Validation< Integer >
notNull.and(lowerThan(100)).test(toValidate).isValid(); //Does not compile
Is there any way to use the Java 8 function features that keep this interface flowing generically, running away from the solutions I've tried above?
thankful
You should relax the generic signature of and, allowing a Validation<T> with a more specific T as parameter, to produce a Validation<T> as result:
default <T extends K> Validation<T> and(Validation<T> other) {
return param -> {
ValidationResult firstResult = this.test(param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
Staying with your examples, you still cannot write
void validate(int toValidate) {
notNull.and(moreThan(100)).test(toValidate).isValid();
}
as moreThan returns a Validation<String> which can not test an int, but spotting such errors is what Generics is all about (I suppose, you have another moreThan method in your actual code base which you didn’t include in your question). But the following will now work with your example:
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
Sometimes, you need to test a validation of a more specific type before a more generic validation which still doesn’t work with the method shown above. One solution would be to go the same route as the JDK developers and augment Function.andThen(after) with a Function.compose(before), allowing to swap the roles
default <T extends K> Validation<T> compose(Validation<T> other) {
return param -> {
ValidationResult firstResult = other.test(param);
return ! firstResult.isValid()? firstResult: this.test(param);
};
}
Or you create a static method, which allows both arguments to have a broader type than the resulting Validation:
static <T> Validation<T> and(Validation<? super T> first, Validation<? super T> second) {
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
Note that the static method can be combined with the convenient instance method, so that the caller only needs to resort to the static method when hitting the limitations of the generic signature:
#FunctionalInterface
public interface Validation<K> {
ValidationResult test(K item);
default <T extends K> Validation<T> and(Validation<T> other) {
return and(this, other);
}
static <T> Validation<T> and(Validation<? super T> first,Validation<? super T> second){
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
}
So you can still write
notNull.and(lowerThan(100)).test(toValidate).isValid();
but when hitting the limitation, e.g.
Validation<Object> anotherCriteria;
…
lowerThan(100).and(anotherCriteria).test(toValidate).isValid();
does not work, you can resort to
Validation.and(lowerThan(100), anotherCriteria).test(toValidate).isValid();
I want to replace the following code using java8 Optional:
public Obj getObjectFromDB() {
Obj obj = dao.find();
if (obj != null) {
obj.setAvailable(true);
} else {
logger.fatal("Object not available");
}
return obj;
}
The following pseudocode does not work as there is no orElseRun method, but anyways it illustrates my purpose:
public Optional<Obj> getObjectFromDB() {
Optional<Obj> obj = dao.find();
return obj.ifPresent(obj.setAvailable(true)).orElseRun(logger.fatal("Object not available"));
}
With Java 9 or higher, ifPresentOrElse is most likely what you want:
Optional<> opt = dao.find();
opt.ifPresentOrElse(obj -> obj.setAvailable(true),
() -> logger.error("…"));
Currying using vavr or alike might get even neater code, but I haven't tried yet.
I don't think you can do it in a single statement. Better do:
if (!obj.isPresent()) {
logger.fatal(...);
} else {
obj.get().setAvailable(true);
}
return obj;
For Java 8 Spring Data offers ifPresentOrElse from "Utility methods to work with Optionals" to achieve what you want.
Example would be:
import static org.springframework.data.util.Optionals.ifPresentOrElse;
ifPresentOrElse(dao.find(), obj -> obj.setAvailable(true), () -> logger.fatal("Object not available"));
You will have to split this into multiple statements. Here is one way to do that:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
obj.ifPresent(o -> o.setAvailable(true));
return obj;
Another way (possibly over-engineered) is to use map:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> {o.setAvailable(true); return o;});
If obj.setAvailable conveniently returns obj, then you can simply the second example to:
if (!obj.isPresent()) {
logger.fatal("Object not available");
}
return obj.map(o -> o.setAvailable(true));
There is an .orElseRun method, but it is called .orElseGet.
The main problem with your pseudocode is that .isPresent doesn't return an Optional<>. But .map returns an Optional<> which has the orElseGet method.
If you really want to do this in one statement this is possible:
public Optional<Obj> getObjectFromDB() {
return dao.find()
.map( obj -> {
obj.setAvailable(true);
return Optional.of(obj);
})
.orElseGet( () -> {
logger.fatal("Object not available");
return Optional.empty();
});
}
But this is even clunkier than what you had before.
First of all, your dao.find() should either return an Optional<Obj> or you will have to create one.
e.g.
Optional<Obj> = dao.find();
or you can do it yourself like:
Optional<Obj> = Optional.ofNullable(dao.find());
this one will return Optional<Obj> if present or Optional.empty() if not present.
So now let's get to the solution,
public Obj getObjectFromDB() {
return Optional.ofNullable(dao.find()).flatMap(ob -> {
ob.setAvailable(true);
return Optional.of(ob);
}).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
}
This is the one liner you're looking for :)
For those of you who want to execute a side-effect only if an optional is absent
i.e. an equivalent of ifAbsent() or ifNotPresent() here is a slight modification to the great answers already provided.
myOptional.ifPresentOrElse(x -> {}, () -> {
// logic goes here
})
Title: "How to execute logic on Optional if not present?"
Answer:
Use orElseGet() as a workaround for the missing ifNotPresent(). And since it expects us to return something just return
null.
Optional.empty().orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
or
Optional.ofNullable(null).orElseGet(() -> {
System.out.println("The object is not present");
return null;
});
//output: The object is not present
I also use it to easily implement the singleton pattern with lazy initialization.
public class Settings {
private Settings(){}
private static Settings instance;
public static synchronized Settings getInstance(){
Optional.ofNullable(instance).orElseGet(() -> instance = new Settings());
return instance;
}
}
Of course the getInstance() content can be written in one line by directly returning the first statement, but I wanted to demonstrate the use of orElseGet() as an ifNotPresent().
I was able to came up with a couple of "one line" solutions, for example:
obj.map(o -> (Runnable) () -> o.setAvailable(true))
.orElse(() -> logger.fatal("Object not available"))
.run();
or
obj.map(o -> (Consumer<Object>) c -> o.setAvailable(true))
.orElse(o -> logger.fatal("Object not available"))
.accept(null);
or
obj.map(o -> (Supplier<Object>) () -> {
o.setAvailable(true);
return null;
}).orElse(() () -> {
logger.fatal("Object not available")
return null;
}).get();
It doesn't look very nice, something like orElseRun would be much better, but I think that option with Runnable is acceptable if you really want one line solution.
With Java 8 Optional it can be done with:
Optional<Obj> obj = dao.find();
obj.map(obj.setAvailable(true)).orElseGet(() -> {
logger.fatal("Object not available");
return null;
});
In order to get the value from one call, or do an extra call if the previous returned an empty value, you can chain the commands.
public Optional<Obj> getObjectFromDB() {
return dao.find().or(() -> dao.findBySomethingElse());
}
You need Optional.isPresent() and orElse(). Your snippet won;t work because it doesn't return anything if not present.
The point of Optional is to return it from the method.
ifPresentOrElse can handle cases of nullpointers as well. Easy approach.
Optional.ofNullable(null)
.ifPresentOrElse(name -> System.out.println("my name is "+ name),
()->System.out.println("no name or was a null pointer"));
I suppose you cannot change the dao.find() method to return an instance of Optional<Obj>, so you have to create the appropriate one yourself.
The following code should help you out. I've create the class OptionalAction,
which provides the if-else mechanism for you.
public class OptionalTest
{
public static Optional<DbObject> getObjectFromDb()
{
// doa.find()
DbObject v = find();
// create appropriate Optional
Optional<DbObject> object = Optional.ofNullable(v);
// #formatter:off
OptionalAction.
ifPresent(object)
.then(o -> o.setAvailable(true))
.elseDo(o -> System.out.println("Fatal! Object not available!"));
// #formatter:on
return object;
}
public static void main(String[] args)
{
Optional<DbObject> object = getObjectFromDb();
if (object.isPresent())
System.out.println(object.get());
else
System.out.println("There is no object!");
}
// find may return null
public static DbObject find()
{
return (Math.random() > 0.5) ? null : new DbObject();
}
static class DbObject
{
private boolean available = false;
public boolean isAvailable()
{
return available;
}
public void setAvailable(boolean available)
{
this.available = available;
}
#Override
public String toString()
{
return "DbObject [available=" + available + "]";
}
}
static class OptionalAction
{
public static <T> IfAction<T> ifPresent(Optional<T> optional)
{
return new IfAction<>(optional);
}
private static class IfAction<T>
{
private final Optional<T> optional;
public IfAction(Optional<T> optional)
{
this.optional = optional;
}
public ElseAction<T> then(Consumer<? super T> consumer)
{
if (optional.isPresent())
consumer.accept(optional.get());
return new ElseAction<>(optional);
}
}
private static class ElseAction<T>
{
private final Optional<T> optional;
public ElseAction(Optional<T> optional)
{
this.optional = optional;
}
public void elseDo(Consumer<? super T> consumer)
{
if (!optional.isPresent())
consumer.accept(null);
}
}
}
}