阿东lazy
2022/11/15阅读:11主题:橙心
Checking for Nulls in Java Minimize Using If Else
Simple and practical articles.
Introduce
In this article, I will try to give some examples of the different types of null checks or NPE (NullPointerException) avoidance techniques that is used.
java.util.Optional
A container object which may or may not contain a non-null value. If a value is present,
isPresent()
will returntrue
andget()
will return the value.
Optional.ofNullable()
Returns an Optional describing the given value, if non-null, otherwise returns an empty Optional.¹
...
return Optional.ofNullable(mongoClient.getDatabase("dbName")
.getCollection("collectionName", Student.class)
.find(eq("id", id))
.first());
...
The returned value from this method will never be null. If it is null, the returned value will be Optional.empty()
.
Optional.orElseThrow()
If a value is present, returns the value, otherwise throws NoSuchElementException.
If you want to throw an exception you could just use orElseThrow()
.
...
return studentDao.findStudentsById(id).orElseThrow(()-> new CustomException(STUDENT_NOT_FOUND));
...
Optional.orElse()
If a value is present, returns the value, otherwise returns other.¹
...
final var student = Student._builder_()
.id(1L)
.name("ege")
.build();
return studentDao.findStudentsById(id).orElse(student);
...
Optional.get()
If a value is present, returns the value, otherwise throws NoSuchElementException.
I mostly use get()
in unit tests when I am sure that there is data returned from the method I called.
But I would not use it without isPresent()
in the actual code, even if I am sure that there will be no null.
The value passed torElse()
is also returned when there is student but no name to it.
@Override
public String getStudentName(Long id) {
return studentDao.findStudentsById(id)
.map(Student::getName)
.orElse("Hayley");
}
apache.commons
-
For Collection instances: CollectionUtils.isEmpty()
orCollectionUtils.isEmpty()
-
For Map instances : MapUtils.isEmpty()
orMapUtils.isNotEmpty()
-
For String : StringUtils.isEmpty()
orStringUtils.isNotEmpty()
My suggestion is to try to use the latest version of the tool classes.
Objects::nonNull
Returns
true
if the provided reference is non-null otherwise returnsfalse
A method commonly used by individuals.
final var list = Arrays._asList_(1, 2, null, 3, null, 4);
list.stream()
.filter(Objects::_nonNull_)
.forEach(System._out_::print);
requireNonNull
requireNonNull()
Checks that the specified object reference is not
null
and throws a customized_NullPointerException_
if it is. This method is designed primarily for doing parameter validation in methods and constructors with multiple parameters.
requireNonNull:“this field is required, so if it is null; throw a NPE with “id is required” message”
requireNonNullElse()
Returns the first argument if it is non-
null
and otherwise returns the non-null
second argument.
requireNonNullElse:"this field is required, so if it is null; don’t throw an exception but set a default value for it"
requireNonNullElseGet()
Returns the first argument if it is non-
null
and otherwise returns the non-null
value ofsupplier.get()
.
requireNonNullElseGet:"this field is required, so if it is null; don’t throw exception but set a default value for it“
The difference from requireNonNullElse
is that, this method expects Supplier
as a second parameter.
NotNull, NotEmpty, NotBlank Annotations
@NotNull
: “The annotated element must not be null. Accepts any type.”
@NotEmpty
: _“The annotated element must not be null or empty. Supported types are CharSequence, Collection, Map, Array.”
@NotBlank
: “The annotated element must not be null and must contain at least one non-whitespace character. Accepts CharSequence”
Below are some examples
@NotNull
private Long id;
@NotEmpty
private String name;
@NotEmpty
private List<SchoolClass> classes;
private Map<Integer, Teacher> teacherMap;
// `@Validated` annotation for the request body of API as below
@PostMapping()
public void saveStudent(@Validated @RequestBody Student student){
studentService.saveStudent(student);
}
Lombok’s Builder.Default
Personally, I have reservations about Lombok, sometimes it's convenient, but sometimes it's annoying.
Below is example:
You can use put @Builder.Default
before the related field and give it a default value.
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Student {
private Long id;
@Builder.Default
private String name = "hayley";
@Builder.Default
private List<SchoolClass> classes = new ArrayList<>();
When an instance of this Student
class is created, it will have “classes” as an empty list, not null.
final var student1 = Student._builder_().build();
final var student2 = new Student();
final var student3 = Student._builder_().id(1L).name("ege").build();
System._out_.println(student1.getClasses());
System._out_.println(student2.getClasses());
System._out_.println(student3.getClasses());
System._out_.println(student1.getName());
System._out_.println(student2.getName());
System._out_.println(student3.getName());
The result:
[]
[]
[]
hayley
hayley
ege
Source References
-
https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html -
https://docs.oracle.com/javase/8/docs/api/java/util/Objects.html -
https://docs.oracle.com/javase/9/docs/api/java/util/Objects.html -
https://docs.oracle.com/javaee/7/api/javax/validation/constraints/NotNull.html -
https://javaee.github.io/javaee-spec/javadocs/javax/validation/constraints/NotEmpty.html -
https://javaee.github.io/javaee-spec/javadocs/javax/validation/constraints/NotBlank.html -
https://www.baeldung.com/java-avoid-null-check -
https://projectlombok.org/
作者介绍
阿东lazy
摸鱼JAVA工程师 公众号:懒时小窝