Tips menangani NullPointerException dengan Java Optional
Bagi programmer Java sudah wajib hukumnya untuk selalu bertemu dengan NullPointerException
, dan ini sebenarnya membuat crash program kita, dan yang jelas kita harus sedikit garuk kepala untuk menangani exception ini. Cara yang paling populer adalah diakali dengan statement kondisi if else
. Untuk menangani ini, Java versi 8 mengenalkan fitur baru yaitu class baru bernama Optional
yang berada pada package java.util
. Class ini sangat membantu sekali untuk menangani null
tanpa harus dicek terlebih dahulu dengan statement kondisi if else
.
Berikut contoh program yang menghasilkan NullPointerException
:
public class DemoOptional {
public static void main(String[] args) {
String[] students = new String[20];
String john = students[10].toUpperCase();
System.out.println("Name : " + john);
}
}
Sekilas program ini tidak ada yang salah, ketika dicompile program ini tidak akan mengalami pesan error, tetapi ketika dieksekusi program ini akan menghasilkan error dikarenakan variable john
yang dipanggil masih belum ada nilainya alias null
.
Ketika program ini di jalankan/run maka akan menghasilkan exception NullPointerException
, karena memang array students index 10 masih bernilai null
.
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.toUpperCase()" because "<local1>[10]" is null
at DemoOptional.main(DemoOptional.java:6)
Nah untuk mengatasinya biasanya dibuatkan statement pemilihan if
untuk menghandle exception tersebut misalnya seperti di bawah ini:
String[] students = new String[20];
// cek nilai apakah null
if (students[10] == null) {
students[10] = "John Doe";
}
String john = students[10].toUpperCase();
System.out.println("Name : " + john);
Output:
Name : JOHN DOE
Contoh penggunaan if
seperti contoh di atas tidaklah salah, tetapi karena seringnya programmer Java mendapatkan permasalahan seperti contoh di atas maka Java 8 membuatkan solusi lain menggunakan class Optional
. Contoh program di atas dapat disederhanakan menggunakan class Optional seperti contoh sebagai berikut:
import java.util.Optional;
public class DemoOptional {
public static void main(String[] args) {
String[] students = new String[20];
String john = Optional.ofNullable(students[10])
.orElse("John Doe").toUpperCase();
System.out.println("Name : " + john);
}
}
Output yang dihasilkan akan sama dengan program sebelumnya tetapi cara yang digunakan sedikit berbeda karena menggunakan class Optional
untuk memeriksa nilai dari student[10]
yang langsung memberikan nilai ketika bernilai Nullable.
Beberapa contoh penggunaan Optional.
Yang berada dalam blok komentar adalah cara manual
Check Null
// String name = customer.getName();
// if (name == null) {
// name = "";
// }
String name = Optional.ofNullable(customer.getName())
.orElse("");
if Logic
// Customer customer = repository.findById("id");
// if (customer == null) {
// customer = repository.createNew();
// }
Customer customer = Optional.ofNullable(repository.findById("id"))
.orElseGet(() -> repository.createNew());
Operation if Not Null
// int id = 2;
// Person person = session.get(Person.class, id);
// if (person != null) {
// System.out.println("Deleting");
// session.delete(person);
// }
int id = 2;
Optional<Person> person = Optional.ofNullable(session.get(Person.class, id));
person.ifPresent(value -> session.delete(value));
Operation to Null Value
// String nameUpper = customer.getName();
// if (nameUpper != null) {
// nameUpper = nameUpper.toUpperCase();
// } else {
// nameUpper = "";
// }
String nameUpper = Optional.ofNullable(customer.getName())
.map(value -> value.toUpperCase())
.orElse("");
nested If Checking
// String country = "Indonesia";
// if (customer.getAddress() != null) {
// if (customer.getAddress().getCountry() != null) {
// country = customer.getAddress().getCountry();
// }
// }
String country = Optional.ofNullable(customer.getAddress())
.map(address -> address.getCountry())
.orElse("Indonesia");
Check and Throw Exception
// String name = customer.getName();
// if (name == null) {
// throw new IllegalArgumentException("Name is null");
// }
String name = Optional.ofNullable(customer.getName())
.orElseThrow(() -> new IllegalArgumentException("Name is null"));
if Check Do Something
// if (customer.getAddress() != null) {
// if (customer.getAddress().getCountry() != null) {
// System.out.println(customer.getAddress().getCountry());
// }
// }
Optional.ofNullable(customer.getAddress())
.map(address -> address.getCountry())
.ifPresent(country -> System.out.println(country));
neested Object
// Long cashBalance = 0L;
// if (customer.getWallet() != null) {
// if (customer.getWallet().getBalance() != null) {
// cashBalance = customer.getWallet().getBalance().getCashBalance();
// }
// }
Long cashBalance = Optional.ofNullable(customer.getWallet())
.map(wallet -> wallet.getBalance())
.map(balance -> balance.getCashBalance())
.orElse(0L);
Filter
// Long bonus = 0L;
// if (CustomerType.PLATINUM.equals(customer.getType())) {
// if (customer.getWallet() != null) {
// if (customer.getWallet().getBalance() != null) {
// bonus = customer.getWallet().getBalance().getCashBalance() * 10 / 100;
// }
// }
// }
Long bonus = Optional.ofNullable(customer)
.filter(value -> CustomerType.PLATINUM.equals(customer.getType()))
.map(value -> value.getWallet())
.map(wallet -> wallet.getBalance())
.map(balance -> balance.getCashBalance())
.map(cashBalance -> cashBalance * 10 / 100)
.orElse(0L);
Download Source Code
Referensi :