Tidak ada yang menyukai NullPointerException! Apakah ada cara untuk menghindarinya? Mungkin. .
Artikel ini akan membahas teknologi berikut
1. Tipe opsional (baru diperkenalkan di Java 8)
2. Kelas objek (asli di Java 7)
Kelas opsional di Java 8
Apa itu?
1. Tipe baru diperkenalkan di Java 8
2. Digunakan sebagai pembungkus untuk objek dengan tipe tertentu atau untuk skenario di mana tidak ada objek (null) yang ada
Sederhananya, ini adalah alternatif yang lebih baik untuk menangani nilai nol (peringatan: ini mungkin tidak begitu jelas pada pandangan pertama)
Penggunaan dasar
Ini adalah tipe (kelas) - jadi bagaimana Anda membuat instance tipe ini?
Cukup gunakan tiga metode statisnya:
Copy kode kodenya sebagai berikut:
public static Opsional<String> stringOpsional(Input string) {
return Opsional.of(input);
}
Sederhana dan jelas - buat pembungkus Opsional yang berisi nilai ini. Ingat - jika nilainya nol, NPE akan dibuang!
Copy kode kodenya sebagai berikut:
public static Opsional<String> stringNullableOptional(Input string) {
jika (!Acakbaru().nextBoolean()) {
masukan = nol;
}
return Opsional.ofNullable(input);
}
Menurut saya pribadi, itu lebih baik. Dengan cara ini tidak akan ada risiko NPE - jika inputnya nol, Opsional kosong akan dikembalikan.
Copy kode kodenya sebagai berikut:
public static Opsional<String> kosongOpsional() {
return Opsional.kosong();
}
Jika Anda benar-benar hanya ingin mengembalikan nilai "null". Nilai "kosong" tidak berarti nol.
Oke, jadi bagaimana cara mengkonsumsi/menggunakan Opsional?
Copy kode kodenya sebagai berikut:
public static void mengkonsumsiOptional() {
Opsional<String> dibungkus = Opsional.of("aString");
if (dibungkus.isPresent()) {
System.out.println("Punya string - " + dibungkus.get());
}
kalau tidak {
System.out.println("Kena!");
}
}
Cara sederhananya adalah dengan memeriksa apakah pembungkus Opsional benar-benar memiliki nilai (menggunakan metode isPresent) - Anda akan bertanya-tanya apa keuntungannya dibandingkan menggunakan if(myObj != null). Jangan khawatir, saya akan menjelaskannya dengan jelas.
Copy kode kodenya sebagai berikut:
public static void memakanNullableOptional() {
Masukan string = nol;
jika (Acak baru().nextBoolean()) {
masukan = "iCanBeNull";
}
Opsional<String> dibungkus = Opsional.ofNullable(input);
System.out.println(wrapped.orElse("default"));
}
Anda dapat menggunakan metode orElse, sehingga jika nilai yang dienkapsulasi memang merupakan nilai null, Anda dapat menggunakannya untuk mengembalikan nilai default - manfaatnya jelas. Saat mengekstraksi nilai sebenarnya, Anda dapat menghindari metode pemanggilan metode ifPresent yang jelas-jelas berlebihan.
Copy kode kodenya sebagai berikut:
public static void mengkonsumsiEmptyOptional() {
Masukan string = nol;
jika (Acak baru().nextBoolean()) {
masukan = "iCanBeNull";
}
Opsional<String> dibungkus = Opsional.ofNullable(input);
System.out.println(dibungkus.orElseGet(
() -> {
kembalikan "defaultBySupplier";
}
));
}
Saya sedikit bingung tentang ini. Mengapa ada dua metode berbeda untuk tujuan yang sama? orElse dan orElseGet jelas dapat kelebihan beban (dengan nama yang sama tetapi parameter berbeda).
Bagaimanapun, perbedaan nyata antara kedua metode ini adalah parameternya - Anda dapat memilih untuk menggunakan ekspresi lambda daripada contoh Pemasok untuk mencapai hal ini (antarmuka fungsional)
Mengapa menggunakan Opsional lebih baik daripada pemeriksaan nol yang umum?
1. Keuntungan terbesar menggunakan Opsional adalah Anda dapat mengungkapkan niat Anda dengan lebih jelas - mengembalikan nilai null akan membuat konsumen bingung (ketika NPE memang terjadi) apakah ini dikembalikan dengan sengaja, jadi Anda harus memeriksa javadoc untuk detail lebih lanjut . Menggunakan Opsional cukup mudah.
2. Dengan Optional, Anda dapat sepenuhnya menghindari NPE - seperti disebutkan di atas, menggunakan Optional.ofNullable, orElse dan orElseGet dapat menjauhkan kita dari NPE.
Penyelamat lainnya!
Lihatlah cuplikan kode ini dan salin kode di bawah ini:
paket com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
impor java.util.Objek;
kelas publik Menggunakan Objek {
String getVal(Peta<String, String> aMap, Kunci string) {
kembalikan aMap.containsKey(kunci) ? aMap.get(kunci) : null;
}
public static void main(String[] args) {
Obj Menggunakan Objek = baru Menggunakan Objek ();
obj.getVal(null, "dummy");
}
}
Yang mana yang mungkin kosong?
1.Objek peta
2. Kunci yang digunakan untuk pencarian
3. Contoh pemanggilan metode ini
Jika NPE dilempar, bagaimana kita bisa menentukan mana yang null?
Copy kode kodenya sebagai berikut:
paket com.abhirockzz.wordpress.npesaviors;
import java.util.Map;
impor java.util.Objek;
kelas publik Menggunakan Objek {
String getValSafe(Peta<String, String> aMap, kunci String) {
Peta<String, String> safeMap = Objek.requireNonNull(aMap,
"Peta adalah nol");
String safeKey = Objects.requireNonNull(kunci, "Kunci adalah null");
kembalikan safeMap.containsKey(safeKey) ? safeMap.get(safeKey) : null;
}
public static void main(String[] args) {
Obj Menggunakan Objek = baru Menggunakan Objek ();
obj.getValSafe(null, "dummy");
}
}
memerlukan metode NonNull
1. Jika objeknya bukan null, kembalikan dirinya sendiri
2. Jika nilainya null, NPE yang dikembalikan akan memiliki pesan yang ditentukan.
Mengapa lebih baik daripada if(myObj!=null)?
Pelacakan tumpukan yang Anda lihat akan dengan jelas melihat pemanggilan metode Objects.requireNonNull. Ini, dikombinasikan dengan log kesalahan Anda sendiri, memungkinkan Anda menemukan masalahnya lebih cepat. . . Setidaknya lebih cepat menurut saya.
Anda juga dapat menyesuaikan validator Anda sendiri, seperti menerapkan validator sederhana untuk memastikan tidak ada nilai null.
Copy kode kodenya sebagai berikut:
impor java.util.Koleksi;
impor java.util.List;
impor java.util.Objek;
import java.util.function.Predikat;
kelas publik RandomGist {
public static <T> T requireNonEmpty(T objek, Predikat<T> predikat, String msgToCaller){
Objek.requireNonNull(objek);
Objects.requireNonNull(predikat);
if (predikat.tes(objek)){
melempar IllegalArgumentException baru(msgToCaller);
}
mengembalikan objek;
}
public static void main(String[] args) {
//Penggunaan 1: string kosong (disengaja)
Tali s = "";
System.out.println(requireNonEmpty(Objects.requireNonNull(s), (s1) -> s1.isEmpty() , "String Saya Kosong!"));
//Penggunaan 2: Daftar kosong (disengaja)
Daftar daftar = Koleksi.emptyList();
System.out.println(requireNonEmpty(Objects.requireNonNull(daftar), (l) -> l.isEmpty(), "Daftar Kosong!").size());
//Penggunaan 3: Pengguna kosong (disengaja)
Pengguna pengguna = Pengguna baru("");
System.out.println(requireNonEmpty(Objects.requireNonNull(pengguna), (u) -> u.getName().isEmpty(), "Pengguna Kosong!"));
}
kelas statis pribadi Pengguna {
nama String pribadi;
Pengguna publik(Nama string){
ini.nama = nama;
}
String publik getName(){
nama kembali;
}
}
}
Jangan sampai NPE menjadi sebuah penyakit yang merugikan. Kita mempunyai banyak alat untuk menangani NPE dengan lebih baik dan bahkan memberantasnya sepenuhnya!