I was going through Java 7 features and they talked about java.util.Objects class.
What I am failing to understand is what is the functional difference betwee
java.util.Objects.toString(foo)
vs
foo == null ? "":foo.toString()
All I could see extra was a null check and functional notation instead of OOP style.
What am I missing ?
The main advantage of java.util.Objects.toString() is that you can easily use it on a return value that might be null, rather than needing to create a new local variable (or worse calling the function twice).
Compare
Foo f = getFoo();
String foo = (f==null) ? "null" : f.toString();
or the cringe-worthy and bug inducing
String foo = (getFoo()==null) ? "null" : getFoo().toString()
to the Objects.toString based version
String foo = Objects.toString(getFoo());
Calling Objects.toString(foo) just removes the need for you to remember to do null checks, and means you can use it directly on a method return value (e.g. Objects.toString(getPossibleNullObject())) without storing it in a variable first (or calling the method twice).
Note however that the method actually returns:
the result of calling toString for a non-null argument and "null" for a null argument
so it is actually equivalent to:
foo == null ? "null" : foo.toString();
if you want "" for a null value you can use the overload that passes a nullDefault return value Objects.toString(foo, "")
Related
I was checking String.valueOf method and found that when null is passed to valueOf it returns "null" string instead of pure java null.
My question is why someone will return "null" string why not pure java null.
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
I am asking this because developer will have to check with equals method for "null" string and not like stringObj != null.
[update]: okay there were down votes for this question, I am not raising question in the api but in my current company there are lot of api which returns "null" string instead of pure java null that is why I asked this question to know whether is it a best practice to return "null" string if we found null string object.
You are looking for Objects#toString(java.lang.Object,java.lang.String)
The call
Objects.toString(obj, null)
returns null when object is null.
Because String.valueOf() returns a String representation, which for a null is "null".
The developer shouldn't be checking the return value at all, since it's meant for display purposes, not for checking whether a reference was null or not.
Because you only want a string representation of null and so it did.
Purpose of this method is to return the String representation.
Check link String.valueOf
I would only use valueOf for displaying something directly. It doesn't offer robust enough validation and sanity checking to pass the output directly into a database, and could lead to incomplete data or data corruption.
Using the following query I discovered there were null-values in the columns.
Select * from tableName x where x.name is null
The java.util.Objects class was extended with a number of new methods
Objects#requireNonNullElse
respectively
Objects#requireNonNullElseGet() in Java-9.
Both will return the first argument if it is non-null and otherwise returns the non-null second argument or the non-null value of supplier.get()
jshell> String nullStr = null;
nullStr ==> null
jshell> Objects.requireNonNullElse(nullStr,"lorem ipsum");
$13 ==> "lorem ipsum"
jshell> Objects.requireNonNullElseGet(nullStr,() -> "lorem ipsum");
$14 ==> "lorem ipsum"
But the new functionality overlaps with already existing in the Optional class Optional#orElse and Optional#orElseGet
jshell> Optional.ofNullable(nullStr).orElse("lorem ipsum");
$17 ==> "lorem ipsum"
jshell> Optional.ofNullable(nullStr).orElseGet(() -> "lorem ipsum");
$18 ==> "lorem ipsum"
The only difference between new methods in Objects and corresponding Optional methods is that second argument or value of supplier must be non-null otherwise Objects throws NPE:
jshell> Objects.requireNonNullElseGet(nullStr,() -> null);
| java.lang.NullPointerException thrown: supplier.get()
| at Objects.requireNonNull (Objects.java:246)
| at Objects.requireNonNullElseGet (Objects.java:321)
| at (#15:1)
jshell> Objects.requireNonNullElse(nullStr,null);
| java.lang.NullPointerException thrown: defaultObj
| at Objects.requireNonNull (Objects.java:246)
| at Objects.requireNonNullElse (Objects.java:301)
| at (#16:1)
versus Optional
jshell> Optional.ofNullable(nullStr).orElse(null);
$19 ==> null
jshell> Optional.ofNullable(nullStr).orElseGet(() -> null);
$20 ==> null
Why haven't the JDK developers updated existing methods in Optional
class?
Why haven't they introduced a new method (which will thrown
NPE if second argument is null) to Optional class?
What should we use now Optional or Objects?
Do new methods make Objects more preferable than Optional since they
will throw NPE immediately and not later on somewhere in the code
like with Optional?
If I have a legacy code, something like:
String str = null;
String result = str == null ? "other string" : str;
Which is just a simple check inside a method. And I would like to re-factor it using latest language features. Now having in mind the difference between Optional.orElse and Objects.requireNonNullOrElse which is preferable?
result = Optional.ofNullable(str).orElse("other string");
or
result = Objects.requireNonNullOrElse(str,"other string);
The shortest answer to your question "which is preferable?" is the all-time developer favorite "it depends" 😜 because Objects::requireNonNullElse and Optional cover different use cases.
The Two Alternatives
Before answering your questions I want to give some background on the two alternatives.
Objects::requireNonNullElse
Objects::requireNonNull makes sure that the result of the call is never null (hence the name). It is usually used to succinctly verify constructor or method arguments and allows readers to verify with a glance that the variable to which the return value is assigned can not be null.
So it would not only be weird for Objects::requireNonNullElse to suddenly allow null, it would also be borderline useless because:
// if requireNonNullGet would allow null as second argument,
// the following is true for all x (including null)
Objects.requireNonNullElse(x, null) == x
You might argue that it is different for requireNonNullElseGet because that might call a function that, depending on some state, might return null or not. That's true and I assume it was considered but the requireNonNull... API would be really weird if one of the three cases might actually allow the final result of the call to be null even though the name says required non null.
Optional
Optional was designed as a return argument in cases where returning null is very likely to cause NPEs (like for a Stream's terminal operation, where it was first used). Although some developers prefer to use it in more cases (compare Stephen Colebourne's pragmatic approach and my strict approach) no one really proposes using it as in your demonstration:
Optional.ofNullable(nullStr).orElse(null);
Optional.ofNullable(nullStr).orElseGet(() -> null);
Optional is a way to express in the type system that something might be missing - it is not meant as an alternative to if-null-checks. In that sense orElse or orElseGet are backdoors out of Optional back into the world of nullable types and sometimes null is just what you want to use if something's not there, so it makes sense for them to accept null as an argument (or the supplier's result).
Your Questions
Now we have what we need to answer your questions:
Why haven't the JDK developers updated existing methods in Optional class?
Conceptually that would go against what Optional should be used for. But, as others have mentioned, this would be a backwards incompatible change as calls to orElse(null) would suddenly throw exceptions.
Why haven't they introduced a new method (which will thrown NPE if second argument is null) to Optional class?
APIs are only extended if considerable improvements of existing code can be expected. I don't see that here. In many cases orElse gets an argument that the caller creates specifically as an alternative for empty optionals - there is rarely a need to make an extra check to verify it's not null. If you really have to, call orElse(requireNonNull(x)).
What should we use now Optional or Objects?
If you have a variable (be it local, an argument or a field) and you want to make sure it's not null, use Objects. If you want to return something, which may be null consider wrapping it in Optional. Be suspicious of code that creates an Optional (as opposed to getting one form a call) and unwraps it at the end of the same chain.
Do new methods make Objects more preferable than Optional since they will throw NPE immediately and not later on somewhere in the code like with Optional?
As I'm sure is clear by now, they cover different use cases. But let me address "and not later on somewhere in the code like with Optional": Whatever you do, make sure to check your desired nullablity property (can be null or not) in your code. Don't return something that you assume can not be null but it turns out to be because you didn't check. If that happens, it's not Optional's fault.
If I have a legacy code, something like:
String str = null;
String result = str == null ? "other string" : str;
Definitely Objects.requireNonNullOrElse(str,"other string"); and consider using static imports to make it more readable.
Why haven't the JDK developers updated existing methods in Optional class?
Because that would introduce a breaking change that would break many existing programs, and because the method should allow getting null if desired.
Why haven't they introduced a new method (which will thrown NPE if second argument is null) to Optional class?
Probably because that would make the API more convoluted and bloated for no significant advantage. You can still wrap the result with requireNonNull if you want to ensure your code doesn't return null unexpectedly.
What should we use now Optional or Objects?
If you need to extract a value out of an optional returned by a method, then use Optional's method. If you want to ensure preconditions are respected for the argument of a method that should not be null, use Object.requireXxx. The JDK designers have never advocated the use of Optional just to wrap a value and check for null. Optional is for return values.
Do new methods make Objects more preferable than Optional since they will throw NPE immediately and not later on somewhere in the code like with Optional?
See previous points: you don't use these methods to do the same thing.
The point is: those two method signatures are clearly different:
public static <T> T requireNonNullElse(T obj, T defaultObj)
vs.
public static <T> T requireNonNullElseGet(T obj, Supplier<? extends T> supplier)
The javadoc for the second method reads:
Returns the first argument if it is non-null and otherwise returns the non-null value of supplier.get().
In other words: it uses the supplier that you provide to it here.
So, the answer is: you use the second version for situations where you want to work with a supplier; and otherwise you simply take the "more simple" version of that method that takes the "less complicated" parameter.
The reasoning behind that: when you decide between two options, you prefer that one that is easier/"less reader surprising" to use. In other words: why would you want to provide a supplier, when you can go without.
Regarding the usage of Optionals - keep in mind that their main goal was to be used for return types; not as method parameters (see here for further reading).
Then: updating existing methods in a class delivered "to the field" is almost always a no-go. You absolutely do not want to change the semantics of something that is already out in the open and used by your customers; assuming specific semantics.
Q. Why haven't the JDK developers updated existing methods in Optional class?
A. Because Optional class was designed to avoid NPE.
Q. Why haven't they introduced a new method (which will thrown NPE if second argument is null) to Optional class?
A. The same answer.
Q. What should we use now Optional or Objects?.
A. Both. Objects for simple "not null" checkings and Optional for chain operations like map, flatMap, `filter'.
Q. Do new methods make Objects more preferable than Optional since they will throw NPE immediately and not later on somewhere in the code like with Optional?
A. Depends on situation. If you already have Optional as return value of some method then it is preferable to use Optional.
So the main point is if you like using ifs for checking for null or not. If you have a method that can take arguments that can be of null value, It would make more sense to use Objects. The only reasonable place to use Optional is to verify a call to a method that returns optional result.
Developers wanted to use more functional way of checking for null values, so the where using the construct Optional.ofNullable for that purpose, which wasn't a good practice, because it was creating garbage.
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.
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
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.
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
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);
}
I want to check for a null pointer when accessing a field several classes deep (in a chain of get methods). However, if one of the earlier methods is null I get a NullPointerException anyways.
This is what I want to check, though it can still get a NullPointerException:
if(x.getLocation().getBuilding().getSolidFuelInd() != null)
pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
This the behavior I want the above code to exhibit:
if(x.getLocation() != null)
if(x.getLocation().getBuilding() != null)
if(x.getLocation().getBuilding().getSolidFuelInd() != null)
pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
The field on the pol is optional and should only be set if the above getter is not null. However the building and location objects could also be null, so now I must check to that they're valid.
Is there any sort of shorter way to check all the above like I want?
With Java 8's Optional<> class, you can map a value as so:
Optional.of(x)
.map(ClassOfX::getLocation)
.map(Location::getBuilding)
.map(Building::getSolidFuelInd)
.map(solidFuelInd -> solidFuelInd ? "Y" : "N")
.ifPresent(pol::setWood_heat_ind);
map calls will only be executed if the value of the optional isn't null thus avoiding the NullPointerException.
ifPresent's purpose is to call your setWood_heat_ind only if a value if available.
A nice single-call equivalent to null checks.
If its code reduction you want then you can save each call in a variable.
// note: Replace type with the correct type
type location = x.getLocation();
type building = location == null ? null : location.getBuilding();
// note: you don't have to check for null on primitive types
pol.setWood_heat_ind(building != null && building.getSolidFuelInd() ? "Y" : "N");
This is much cleaner and easier to follow.
Food for thought, you don't check for null on primitive types boolean, int, byte etc. so the last null check on building.getSolidFuelInd() is not needed
Java 8 has Optional<T> which would make for one chained expression, though verbose.
However Java 8 also has Stream<T> and you could have a
"stream" of 0 or 1 item, and then query with lambdas.
x.getLocation()
.map((loc) -> loc.getBuilding())
.map((building) -> building.getSolidFuelInd() != null)
.findFirst()
.ifPresent ...
Or
x.getLocation()
.map(Location::getBuilding)
.map(Building::getSolidFuelInd())
.filter(fuelInd -> fuelId != null)
.findFirst()
.ifPresent ...
It probably will be a matter of slow coming to terms with an application of those new terms.
You could just catch the exception
try{
pol.setWood_heat_ind(x.getLocation().getBuilding().getSolidFuelInd() ? "Y" : "N");
}catch(NullPointerException e){
//e.printStackTrace(); or whatever you want
}
(Referring to your possible solution) checking for the returned values implies invoking the same methods more the once, that's why I would use this solution.
As Jay Harris pointed out, you can obviously check the values and save the return parameter, without having to invoke the same method again. You can do it in many different ways, here one
Object loc=null,build=null;
Boolean SFI = ((loc=x.getLocation())==null?null:
((build=loc.getBuilding())==null?null:
(build.getSolidFuelInd())));
if(SFI!=null)pol.setWood_heat_ind(SFI?"Y":"N");
But is it worth it? I made this more complicated than it could on purpose, but anyway, why doing that if you can try...catch in two simple lines?
I have a scenario which I want to use Guava Optional, but there is problem:
The method is like this:
private static void method(Optional<Object> myOptional) {
if(myOptional.isPresent()) {
....
}
}
The myOptional can contain non-null value, null value, or absent(). A null is a valid input in this scenario.
In the method, I want to process non-null value and null value using differnt ways, but ignore absent value.
However, if I use isPresent here, the null value will be ignored as well. But if I use "get" method, the absent value will throw exception. If I use orNull, the absent value also returns as null.
I am not sure what I shall do here. But I think the reason to create Optional is to differentiate null and absent so that null becomes a valid meaningful value. But it looks like there is no method in Optional that allows me to achieve my usecase.
Can anyone help? Thanks.
You can't do that.
The javadoc says it explicitly: an Optional may contain a non null reference. Never a null one.
What you can do is create an Optional.fromNullable(whatever).orNull(). But an Optional will never differentiate a null value from absent, since it is not what it is meant to do!