NullPointerException là gì?
NullPointerException (NPE) là lỗi ngoại lệ xảy ra khi lập trình viên tham chiếu tới Object nhưng nó lại không có vị trí nào trên bộ nhớ (null). Gọi một method tham chiếu null hoặc cố gắng truy cập một trường tham chiếu null là một trong những nguyên nhân phổ biến gây ra lỗi Null Pointer Exception.
Theo JavaDoc, NPE được gây ra bởi những nguyên nhân:
Ném null như kiểu nó là một giá trị Throwable.
Gọi một Instance method của một null object.
Truy cập hoặc tùy chỉnh trường giá trị của null object.
.Lấy độ dài của Null như một mảng.
Truy cập hoặc tùy chỉnh giá trị Null như kiểu một mảng.
Làm cách nào để thực sự phòng tránh được lỗi java.lang.NullPointerException khi chạy chương trình?
Bài viết sẽ điểm qua một vài ví dụ gây ra lỗi NPE và những cách giải quyết:
Chúng ta tạo lỗi NullPointerException theo 3 cách khác nhau:
Gây lỗi NPE nếu bạn cố gắng truy nhập null Object.
Gây lỗi NPE nếu bạn cố đổi null String.
Gây lỗi NPE nếu bạn cố truy nhập null Object trong quá trình khởi tạo Class.
Tạo class mẫu như dưới đây: NullPointerExceptionTechmasterVN.java
package techmaster.edu.java;
public class NullPointerExceptionTechmasterVN {
public static void main(String[] args) {
try {
// VD1: Lỗi NPE xảy ra nếu bạn cố truy nhập một null Object
TechmasterNPE1();
} catch (NullPointerException techmaster1) {
System.out.println("Exception in TechmasterNPE1()");
techmaster1.printStackTrace();
}
try {
// VD2: Lỗi NPE xảy ra khi bạn có đổi một null String
TechmasterNPE2();
} catch (NullPointerException techmaster2) {
System.out.println("\nException in TechmasterNPE2()");
techmaster2.printStackTrace();
}
try {
//VD 3: Lỗi NPE xảy ra khi bạn cố truy nhập
//null Object trong quá trình khởi tạo class
TechmasterNPETest npe = new TechmasterNPETest();
npe.getName();
} catch (NullPointerException npe3) {
System.out.println("\n Exception in TechmasterNPETest()");
npe3.printStackTrace();
}
}
private static void TechmasterNPE1() {
Object techmasterObj = null;
techmasterObj.hashCode();
}
private static void TechmasterNPE2() {
String techmasterString;
//Chúng ta gọi một biến techmasterString có kiểu giá trị String
//Biên chưa trỏ tới giá trị cụ thể, nên Java mặc định giá trị nó là null
techmasterString = "http://techmaster.vn";
//Sau dòng lệnh trên, biến được gọi giá trị cụ thể
//với giá trị cụ thể trên bộ nhớ
// nên sẽ không bị lỗi NullPointerException
System.out.println("\nvalue: " + techmasterString.toString() + ", lenght: " + techmasterString.length());
System.out.println("No NPE exception");
// Giờ tạo ra lỗi NullPointerException nào
String techmasterString2 = null;
System.out.println(techmasterString2.toString());
}
}
class TechmasterNPETest {
private String techmasterName;
public void setName(String name) {
this.techmasterName = name;
}
public void getName() {
printName(techmasterName);
}
private void printName(String s) {
System.out.println(s + " (" + s.length() + ")");
}
}
Két quả như sau:
Exception in TechmasterNPE1()
java.lang.NullPointerException
at techmaster.edu.java.NullPointerExceptionTechmasterVN.TechmasterNPE1(NullPointerExceptionTechmasterVN.java:34)
at techmaster.edu.java.NullPointerExceptionTechmasterVN.main(NullPointerExceptionTechmasterVN.java:7)
value: http://techmaster.vn, lenght: 20
No NPE exception
Exception in TechmasterNPE2()
java.lang.NullPointerException
at techmaster.edu.java.NullPointerExceptionTechmasterVN.TechmasterNPE2(NullPointerExceptionTechmasterVN.java:51)
at techmaster.edu.java.NullPointerExceptionTechmasterVN.main(NullPointerExceptionTechmasterVN.java:15)
Exception in TechmasterNPETest()
java.lang.NullPointerException
at techmaster.edu.java.TechmasterNPETest.printName(NullPointerExceptionTechmasterVN.java:68)
at techmaster.edu.java.TechmasterNPETest.getName(NullPointerExceptionTechmasterVN.java:64)
at techmaster.edu.java.NullPointerExceptionTechmasterVN.main(NullPointerExceptionTechmasterVN.java:24)
Dưới đây là một vài mẹo tránh lỗi NullPointerException:
#1: Sử dụng gợi ý trên IDE tránh lỗi
#2: Tạo một methode kiểm tra Object.
Bổ sung method vào class NullPointerExceptionTechmasterVN.java
public static boolean techmasterIsNullOrEmpty(String techmasterString) {
if (techmasterString == null)
return true;
else if (techmasterString.trim().equals(""))
return true;
else
return false;
}
Ta sửa lại code lại methode TechmasterNPE2() trong class chính.
String techmasterString2 = null;
System.out.println(techmasterString2.toString());
if (!techmasterIsNullOrEmpty(techmasterString2)) {
System.out.println(techmasterString2.toString());
} else {
System.out.println("techmasterString2 có giá trị null");
}
#3: Kiểm tra String null sau lệnh thực thi trim()
public static boolean isNullOrEmptyAfterTrim(String techmasterString) {
return (techmasterString == null || techmasterString.trim().length() == 0);
}
#4: Luôn sử dụng cấu trúc Try Catch bắt lỗi NullPointerException
try {
TechmasterNPE1();
} catch (NullPointerException techmaster1) {
System.out.println("Exception in CrunchifyNPE1()" + techmaster1);
}
#5: Sử dụng Collections.emptyList()
Collections.emptyList()
#6: Sử dụng Java Assertions
assert <Expression>;
assert <Expression1> : <Expression2>;
// bổ sung thêm vào class chính
private void printName(String s) {
assert (s != null) : "Name must be not null";
System.out.println(s + " (" + s.length() + ")");
}
#7: Sử dụng containsKey(), containsValue(), contains() để kiểm tra giá trị null.
package techmaster.edu.java;
import java.util.HashMap;
public class ContainKeyExample {
public static void main(String args[]) {
HashMap<Integer, String> techmasterMap = new HashMap<Integer, String>();
// Khởi tạo cách giá trị cho HashMap
techmasterMap.put(1, "Ngọc Trinh");
techmasterMap.put(2, "Angela Phương Trinh");
techmasterMap.put(3, "Kì Duyên");
// kiểm tra sự tồn tại của key số 4
if (techmasterMap.containsKey(4)) {
System.out.println("Nếu key 2 tồn tại thì: " + techmasterMap.get(4));
} else {
System.out.println("Tránh được lỗi NullPointerException cho key 4");
}
}
}
Chạy thử class trên, bạn sẽ ra kết quả in chuỗi: "Tránh được lỗi NullPointerException cho key 4".
#8: Viết code thật khôn ngoan:
Hãy cùng xem hai đoạn code dưới đây:
public boolean checkName(String name) {
return name.equalsIgnoreCase("Tăng Thanh Hà");
}
Khi biến name trong methode trên là null, chúng ta sẽ gặp lỗi NullPointerException.
Có thể khắc phục theo cách sau:
public boolean checkName(String name) {
return "Tăng Thanh Hà".equalsIgnoreCase(name);
}
Chuỗi String "Tăng Thanh Hà" được đặt ở đầu là một đối tượng không bao giờ null nên khi chúng ta sử dụng nó để so sánh với giá trị của biến name, NullPointerException sẽ không bao giờ xảy ra.
Hãy luyện tập các ví dụ trên thử nhé, bạn sẽ tiết kiệm được kha khá thời gian trong tương lai khi làm chủ được lỗi NullPointerException đó.
Nguồn: crunchify
Bình luận