Method 4 is best.
if(foo != null && foo.bar()) {
someStuff();
}
will use short-circuit evaluation, meaning it ends if the first condition of a logical AND is false.
Method 4 is best.
if(foo != null && foo.bar()) {
someStuff();
}
will use short-circuit evaluation, meaning it ends if the first condition of a logical AND is false.
The last and the best one. i.e LOGICAL AND
if (foo != null && foo.bar()) {
etc...
}
Because in logical &&
it is not necessary to know what the right hand side is, the result must be false
Prefer to read :Java logical operator short-circuiting
You can chain all of those calls via Optional::map. I sort of find this easier to read than if/else, but it might be just me
Optional.ofNullable(person.getClothes())
.map(Clothes::getCountry)
.map(Country::getCapital)
.ifPresent(...)
These "cascade" null-checks are really paranoid and defensive programming. I'd start with a question, isn't better to make it fail fast or validate the input right before it's store into such a data structure?
Now to the question. As you have used nested the null-check, you can do the similar with Optional<T> and a method Optional::map which allows you to get a better control:
Optional.ofNullable(person.getClothes())
.map(clothes -> clothes.getCountry())
.map(country -> country.getCapital())
.orElse(..) // or throw an exception.. or use ifPresent(...)
The follwoing code worked well for me:
Optional.of(new Outer())
.map(Outer::getNested)
.map(Nested::getInner)
.map(Inner::getFoo)
.ifPresent(System.out::println);
I highly suggest you watch the recent Devoxx Belgium presentation "Optional - The Mother of All Bikesheds" by Stuart Marks. Stuart is describing what was the initial intent, best practices and bad practices using it.
In particular using Optional in fields, quoting from the presentation slide:
- Why Not Use Optional in Fields?
- More a style issue than a correctness issue
- use of Optional in fields often arises from slavish desire to eliminate nullable fields.
- remember, eliminating nulls isn't a goal of Optional
- Using Optional in fields..
- creates another object for every field
- introduces a dependent load from memory on every field read
- clutters up your code
- to what benefit? ability to chain methods?
To your example in particular:
- why
outer != nullcheck? it's just got created! - if
Nestedinstance needs to be part ofOuterandInnerpart ofNestedhave them part of the constructors and guard with some@NotNullcode or check programmatically.
I'm coming back to Java after almost 10 years away programming largely in Haskell. I'm wondering how folks are checking their null-safety. Do folks use CheckerFramework, JSpecify, NullAway, or what?
Style 2 isn't going Java 8 enough to see the full benefit. You don't want the if ... use at all. See Oracle's examples. Taking their advice, we get:
Style 3
// Changed EmployeeServive to return an optional, no more nulls!
Optional<Employee> employee = employeeServive.getEmployee();
employee.ifPresent(e -> System.out.println(e.getId()));
Or a more lengthy snippet
Optional<Employee> employee = employeeServive.getEmployee();
// Sometimes an Employee has forgotten to write an up-to-date timesheet
Optional<Timesheet> timesheet = employee.flatMap(Employee::askForCurrentTimesheet);
// We don't want to do the heavyweight action of creating a new estimate if it will just be discarded
client.bill(timesheet.orElseGet(EstimatedTimesheet::new));
If you're using Optional as a "compatibility" layer between an older API that may still return null, it may be helpful to create the (non-empty) Optional at the latest stage that you're sure that you have something. E.g., where you wrote:
Optional<Employee> employeeOptional = Optional.ofNullable(employeeService.getEmployee()); if(employeeOptional.isPresent()){ Employee employeeOptional= employeeOptional.get(); System.out.println(employee.getId()); }
I'd opt toward:
Optional.of(employeeService) // definitely have the service
.map(EmployeeService::getEmployee) // getEmployee() might return null
.map(Employee::getId) // get ID from employee if there is one
.ifPresent(System.out::println); // and if there is an ID, print it
The point is that you know that there's a non-null employee service, so you can wrap that up in an Optional with Optional.of(). Then, when you call getEmployee() on that, you may or may not get an employee. That employee may (or, possibly, may not) have an ID. Then, if you ended up with an ID, you want to print it.
There's no need to explicitly check for any null, presence, etc., in this code.
If null is a reasonable input parameter for your method, fix the method. If not, fix the caller. "Reasonable" is a flexible term, so I propose the following test: How should the method hande a null input? If you find more than one possible answer, then null is not a reasonable input.
Don't use null, use Optional
As you've pointed out, one of the biggest problems with null in Java is that it can be used everywhere, or at least for all reference types.
It's impossible to tell that could be null and what couldn't be.
Java 8 introduces a much better pattern: Optional.
And example from Oracle:
String version = "UNKNOWN";
if(computer != null) {
Soundcard soundcard = computer.getSoundcard();
if(soundcard != null) {
USB usb = soundcard.getUSB();
if(usb != null) {
version = usb.getVersion();
}
}
}
If each of these may or may not return a successful value, you can change the APIs to Optionals:
String name = computer.flatMap(Computer::getSoundcard)
.flatMap(Soundcard::getUSB)
.map(USB::getVersion)
.orElse("UNKNOWN");
By explicitly encoding optionality in the type, your interfaces will be much better, and your code will be cleaner.
If you are not using Java 8, you can look at com.google.common.base.Optional in Google Guava.
A good explanation by the Guava team: https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained
A more general explanation of disadvantages to null, with examples from several languages: https://www.lucidchart.com/techblog/2015/08/31/the-worst-mistake-of-computer-science/
@Nonnull, @Nullable
Java 8 adds these annotation to help code checking tools like IDEs catch problems. They're fairly limited in their effectiveness.
Check when it makes sense
Don't write 50% of your code checking null, particularly if there is nothing sensible your code can do with a null value.
On the other hand, if null could be used and mean something, make sure to use it.
Ultimately, you obviously can't remove null from Java. I strongly recommend substituting the Optional abstraction whenever possible, and checking null those other times that you can do something reasonable about it.
I'm 4 y experienced Java dev but still it's unclear how and when to check nullity sometimes and it happened today. Let's say there is a table called students and it has column called `last_name` which is not null.
create table students (
last_name varchar(255) not null
)You have written validation code to ensure all required column is appeared while inserting new record and there is a method that needs last_name of students. The parameter of this method may or may not come from DB directly(It could be mapped as DTO). In this case do you check nullity of `last_name` even though you wrote validation code? Or just skip the null check since it has not null constraint?
I know this depends on where and how this method is used and i skipped the null check because i think this method is not going to be used as general purpose method only in one class scope.
public static <T> T ifNull(T toCheck, T ifNull) {
if (toCheck == null) {
return ifNull;
}
return toCheck;
}
All in all to avoid statement
if (object != null) {
....
}
since java 7 you can use
Objectsmethods:Objects.isNull(object)
Objects.nonNull(object)
Objects.requireNonNull(object)
Objects.equals(object1, object2)
since java 8 you can use Optional class (when to use)
object.ifPresent(obj -> ...); java 8
object.ifPresentOrElse(obj -> ..., () -> ...); java 9
rely on method contract (JSR 305) and use Find Bugs. Mark your code with annotations
@javax.annotation.Nullableand@javax.annotation.Nonnnul. Also Preconditions are available.Preconditions.checkNotNull(object);
In special cases (for example for Strings and Collections) you can use apache-commons (or Google guava) utility methods:
public static boolean isEmpty(CharSequence cs) //apache CollectionUtils
public static boolean isEmpty(Collection coll) //apache StringUtils
public static boolean isEmpty(Map map) //apache MapUtils
public static boolean isNullOrEmpty(@Nullable String string) //Guava Strings
- When you need to assign default value when null use apache commons lang
public static Object defaultIfNull(Object object, Object defaultValue)
The dilemma
If a variable with null value gets used in your program causing a NullPointerException, this is clearly a situation in your program which you did not expect. You must ask yourself the question: "Did I not expect it because I didn't take into consideration the possibility of a null value or did I assume the value could never be null here?"
If the answer is the latter, the problem isn't because you didn't handle the null value. The problem happened earlier, and you're only seeing the consequence of that error on the particular line it's used. In this case, simply adding a if (variable != null) isn't going to cut it. You'll wind up skipping lines you were supposed to execute because the variable was null, and you'll ultimately hit a line further on where you again assumed it wouldn't be null.
When null should be used
As a general rule, return null only when "absent" is a possible return value. In other words, your data layer may search for a record with a specific id. If that record isn't found, you can either throw an exception or simply return null. You may do either, but I prefer not to throw exceptions in situations where the strong possibility exists. So you return null instead of a value.
The caller of this method, presumably written by you, knows the possibility exists that the record may not exist and checks for null accordingly. There is nothing wrong with this in this case, though you should handle this possibility as soon as possible as otherwise everywhere in your program you will need to deal with the possibility of a null value.
Conclusion
In other words, treat null as a legitimate value, but deal with it immediately rather than wait. Ideally in your program, you should ever only have to check if it is null once in your program and only in the place where such a null value is handled.
For every value you expect to be non-null, you need not add a check. If it is null, accept that there is an error in your program when it was instantiated. In essence, favor fail fast over fail safe.
Deciding whether or not null is a allowed as an object value is a decision that you must make consciously for your project.
You don't have to accept a language construct just because it exists; in fact, it is often better to enforce a strict rule against any nullvalues in the entire project. If you do this, you don't need checks; if a NullPointerException ever happens, that automatically means that there is a defect in your code, and it doesn't matter whether this is signalled by a NPE or by some other sanity check mechanism.
If you can't do this, for instance because you have to interoperate with other libraries that allow null, then you do have to check for it. Even then it makes sense to keep the areas of code where null is possible small if possible. The larger the project, the more sense it makes to define an entire "anti-corruption layer" with the only purpose of preserving stricter value guarantees than is possible elsewhere.
You can do:
Optional.ofNullable(names).orElse(Collections.emptyList()).forEach(System.out::println);
or
Optional.ofNullable(names).ifPresent(n -> n.forEach(System.out::println));
or
Stream.of(names)
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.forEach(System.out::println);
but don't. Look at all all that extra stuff you'd have to write.
Just use a plain old null check, like you have in your code already.
As the Answer by Andy Turner suggest, writing a plain null check is best here.
Objects.nonNull
But Java 8 does offer one minor improvement: methods on the Objects utility class for the null check.
Objects.isNullObjects.nonNull
So your code would like this.
List<String> names = service.serviceCall();
if( Objects.nonNull( names ) )
{
names.forEach( System.out::println );
}
Objects.requireNonNullElseGet
Another method on Objects can return an alternate object if that suits your situation. For example, if your service call returns null list, perhaps you should substitute an empty list. Call Objects.requireNonNullElseGet.
The lambda passed is handled in a lazy manner, not executed unless needed.
List<String> names =
Objects.requireNonNullElseGet
(
service.serviceCall() ,
() -> new ArrayList<>( 0 ) // In Java 9 and later, use `List.of()`.
)
;
names.forEach( System.out::println );
Your solution is very smart. The problem I see is the fact that you don't know why you got a null? Was it because the house had no rooms? Was it becuase the town had no houses? Was it because the country had no towns? Was it because there was a null in the 0 position of the collection because of an error even when there are houses in positions 1 and greater?
If you make extensibe use of the NonPE class, you will have serious debugging problems. I think it is better to know where exactly the chain is broken than to silently get a null that could be hiding a deeper error.
Also this violates the Law of Demeter: country.getTown().getHouses().get(0).getLivingRoom(). More often than not, violating some good principle makes you have to implement unorthodox solutions to solve the problem caused by violating such principle.
My recommendation is that you use it with caution and try solve the design flaw that makes you have to incur in the train wreck antipattern (so you don't have to use NonPE everywhere). Otherwise you may have bugs that will be hard to detect.
The idea is fine, really good in fact. Since Java 8 the Optional types exist, a detailed explanation can be found at Java Optional type. A example with what you posted is
Optional.ofNullable(country)
.map(Country::getTown)
.map(Town::Houses);
And further on.