Lỗi java lang numberformatexception for input string null năm 2024

Hôm trước có ngồi uống nước với anh sếp, anh ý có hỏi mình một câu là “Đã biết cách Handle Exceptions trong java như nào chưa”.

Thực sự trước giờ làm mình cũng không để ý cái này cho lắm nên khi bị hỏi thì mình trả lời như này “là xử lý ngoại lệ khi bắt gặp một lỗi phát sinh” “Xử lý như thế nào ?” anh ý hỏi tiếp, nhìn mặt mình chắc biết không trả lời được nên bảo về tìm hiểu.

Sau một hồi tra google, tìm hiểu tài liệu thì mình đúc kết được 9 cách sau đây. Có thể không đầy đủ nhưng đây là thành quả mình tìm hiểu được 😀

Xư lý ngoại lệ trong java không phải là 1 vấn đề dễ dàng, nhất là đối với những người còn thiếu kinh nghiệm và mới bước vào nghề như mình. Theo mình tìm hiểu thì đa phần các nhóm phát triển đều có bộ quy tắc riêng và cách sử dụng chúng nên việc bài viết của mình có thể sẽ khác so với các quy tắc của các bạn đã làm trước đây. Tuy nhiên có một quy tắc được hầu hết các đội ngũ sử dụng, và bài viết này sẽ tổng hợp lại những cách mà bản thân mình đã tìm hiểu được.

Trước tiên đi sâu vào tìm hiểu thì hãy thử trả lời 2 câu hỏi bên dưới : – Ngoại lệ là gì, và tại sao chúng ta cần xử lý ngoại lệ ? – Tại sao chúng ta lại cần chúng ? Sau khi trả lời thì chúng ta sẽ bắt đầu đi sâu vào việc nghiên cứu, tuy nhiên nếu các bạn không muốn trả lời 2 câu hỏi bên trên hoặc không biết câu trả lời thì các bạn có thể .

Ok, Bắt đầu thôi nào 😀

-Giới thiệu và tóm tắt :

Ngoại lệ là gì ? và xử lý ngoại lệ là gì ? Trước tiên đi sâu vào tìm hiểu thì chúng ta cần biết nó là gì và tại sao chúng ta cần phải xử lý nó.

-Xác định ngoại lê :

Cùng trả lời câu hỏi, ngoại lệ là gì ? – Hiểu một cách đơn giản ngoại lệ là tất cả các trường hợp bất thường trong quá trình thực thi chương trình. Một ngoại lệ xảy ra khi có sự cố, ví dụ như bạn mở 1 tệp tin mà nó không tồn tại hay là lấy giá trị từ 1 biến null. Và boommmm, 1 ngoại lệ đã xảy ra.

Lỗi java lang numberformatexception for input string null năm 2024

Ngoại lệ là một thứ tồi tệ mà chúng ta phải giả định rằng nó sẽ xảy ra, nhưng trước khi nó xảy ra thì chúng ta cần phải xử lý nó. Xử lý ngoại lệ là một cơ chế xử lý lỗi, khi có lỗi xảy ra, một ngoại lệ sẽ được bắn ra. Và nếu chúng ta không xử lý nó một cách đúng đắn thì rất có thể chương trình của chúng ta sẽ bị lỗi và dẫn đến việc không thể tiếp tục hoạt động được nữa.

Hoặc bạn có thể chọn việc xử lý ngoại lệ, thực hiện các bước để ngăn chương trình bị lỗi và tìm cách khôi phục chúng. Hoặc bạn có thể mặc kệ và để chương trình của bạn “chết” một cách nhẹ nhàng 😀 Mình nghĩ đa phần các bạn đã đọc được đến đây rồi thì không ai chọn cách thứ 2 đâu nhỉ. Ok tiếp tục nào…

-Xử lý lỗi như trước đây:

Như bạn đã đọc, xử lý ngoại lệ là một cơ chế xử lý lỗi, nhưng nó không phải là cơ chế duy nhất. Ngày nay, đại đa số các ngôn ngữ lập trình cung cấp xử lý ngoại lệ như một tính năng, nhưng mọi thứ luôn luôn theo cách này. Vậy làm như thế nào để các ngôn ngữ lập trình có thể đưa ra 1 quy tắc chung khi gặp lỗi. Một cách tiếp cận phổ biến là trả về mã lỗi. Chẳng hạn, giả sử bạn có hàm X chứa mảng số nguyên và một số nguyên duy nhất rồi tìm kiếm và trả về thứ tự của giá trị đầu tiên trong mảng được tìm thấy. Ví dụ: 1 mảng bao gồm 5 số nguyên {1,2,3,4,1} và bạn muốn tìm ra thứ tự của số 1. Trong mảng có 2 số 1 và đương nhiên thứ tự số 1 đầu tiên được tìm thấy sẽ là thự tự đầu tiên. Nhưng nếu bạn muốn tìm số 5 trong mảng trên, bạn sẽ làm gì khi không tìm được giá trị trong mảng trên, bạn sẽ trả về thứ tự là bao nhiều ? Một lựa chọn phổ biến sẽ là trả về -1

Lỗi java lang numberformatexception for input string null năm 2024

Cách tiếp cận này có ưu điểm là giữ cho các mã lỗi được thể hiện 1 cách rõ ràng, với mỗi lỗi sẽ có một mô tả lỗi khác nhau. Ví dụ như khi nhắc tới lỗi 404 là ai cũng sẽ biết là lỗi Not Found. Nhưng một nhược điểm của việc này là sự thiếu rõ ràng, ví dụ như khi trả về mã -5. Điều này có ý nghĩa là một số tập tin đã được tìm thấy. Nhưng tập tin nào ? Một mã lỗi không thể mô tả được điều này.

Một cách khác thay cho việc trả về mã lỗi là bạn có thể trả về giá trị, điều này sẽ giúp việc mô tả lỗi được rõ ràng hơn.

– Giải quyết các ngoại lệ

Các trường hợp ngoại lệ xuất hiện để giải quyết các vấn đề mà bạn vừa đọc. Khi một ngoại lệ được ném ra, luồng điều khiển của chương trình bị gián đoạn. Nếu không ai xử lý ngoại lệ, nó sẽ khiến chương trình bị sập. Người dùng sẽ có thể nhìn thấy các ngoại lệ, và đương nhiên sẽ mang lại trải nghiệm không tốt cho người dùng. Không ai muốn việc đang lướt web mà tự nhiên một thông báo lỗi hiện ra che hết màn hình của họ cả.

Lỗi java lang numberformatexception for input string null năm 2024

Vì vậy bạn sẽ muốn xử lý các ngoại lệ đó mặc dù nó chỉ là các lỗi rất nhỏ. Và để xử lý ngoại lệ thì chúng ta xử lý bằng cách bắt nó khi mà trương trình ném cho chúng ta 😀 Chúng ta làm việc này bằng sử dụng exception-handling block.

Khi chúng ta bắt được một ngoại lệ, chúng ta sẽ điều khiển luồng xử lý của chương trình đến chỗ xử lý ngoại lệ và xử lý nó. Đọc thì thấy khó hiểu đúng không =)) Hãy đọc tiếp và chúng ta sẽ thấy những ví dụ cụ thể hơn.

-Các ngoại lệ Java hoạt động như thế nào ?

hãy nhìn vào ví dụ dưới đây

package com.company;
import java.io.*;
public class Main { 
    public static void main(String[] args){ 
        System.out.println("First line");
        System.out.println("Second line");
        System.out.println("Third line");
        int[] myIntArray = new int[]{1, 2, 3};
        print4hItemInArray(myIntArray);
        System.out.println("Fourth line");
        System.out.println("Fith line");
    } 
    private static void print4thItemInArray(int[] arr) {
        System.out.println(arr[3]);
        System.out.println("Fourth element successfully displayed!");
    }
}

Đoạn mã trên in một số thông điệp vô thưởng vô phạt chỉ nói chúng thuộc dòng nào. Sau khi in dòng thứ ba, mã khởi tạo một mảng với ba số nguyên và truyền nó dưới dạng đối số cho một phương thức riêng. Phương thức này cố gắng in mục thứ tư trong mảng, mục thứ tư này không tồn tại, điều này khiến một ngoại lệ đã xảy ra: ArrayIndexOutOfBoundsException exception to be thrown. Khi điều đó xảy ra, việc thực thi chương trình bị dừng lại và thông báo ngoại lệ được hiển thị và các lệnh in ra sau đó sẽ không bao giờ được thực thi. đây là kết quả đầu ra

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
  at com.company.Main.print4hItemInArray(Main.java:26)
  at com.company.Main.main(Main.java:13)
First line
Second line
Third line

Bầy giờ chúng ta sẽ xử lý bằng việc thêm một số xử lý ngoại lệ vào.

package com.company;
import java.io.*;
public class Main {
    public static void main(String[] args) {
  // write your code here
      System.out.println("First line");
      System.out.println("Second line");
      System.out.println("Third line");
      try {
          int[] myIntArray = new int[]{1, 2, 3};
          print4thItemInArray(myIntArray);
      } catch (ArrayIndexOutOfBoundsException e){
          System.out.println("The array doesn't have four items!");
      }
      System.out.println("Fourth line");
      System.out.println("Fith line");
    }
    private static void print4thItemInArray(int[] arr) {
        System.out.println(arr[3]);
    }
}

Bây giờ, sau khi chạy đoạn code, đây là đầu ra chúng ta nhận được:

First line
Second line
Third line
The array doesn't have four items!
Fourth line
Fith line

Lần này, ngoại lệ vẫn xảy ra, nhưng khác với bên trên. Chúng ta đã xử lý và chương trình không hề bị lỗi. Khi nói đến việc xử lý các trường hợp ngoại lệ trong Java, có nhiều điều hơn thế so với phần giới thiệu ngắn gọn của mình. Vì vậy các bạn có thể lick vào đây để tìm hiểu chi tiết hơn.

Và không lan man nữa, dưới đây sẽ là 9 cách xử lý ngoại lệ mà mình sẽ giới thiệu với các bạn. Một vài lưu ý là có những câu mình sẽ để nguyên tiếng anh vì khi nếu dịch qua tiếng việt thì có thể sẽ không thể hiện được chính xác và đẩy đủ nội dung, tiếng anh của mình có hạn nên mình sẽ cố gắng hết sức =))) chỗ nào k đúng mọi người bỏ qua nhé.

1. Clean Up Resources in a Finally Block or Use a Try-With-Resource Statement

Thì ý nghĩa câu trên hiểu đơn giản là bạn phải xử lý resource của bạn ở khối cuối cùng hoặc nên dùng với Try-With-Resource

Lấy ví dụ cho dễ hiểu nhé, cùng nhìn xuống đoạn code bên dưới.

public void doNotCloseResourceInTry() {
  FileInputStream inputStream = null;
  try {
    File file = new File("./tmp.txt");
    inputStream = new FileInputStream(file);
    // use the inputStream to read a file
    // do NOT do this
    inputStream.close();
  } catch (FileNotFoundException e) {
    log.error(e);
  } catch (IOException e) {
    log.error(e);
  }
}

Đây là cách đơn giản để bạn có thể mở một file với inputStream. Nếu các bạn chưa biết inputStream là gì thì có thể ấn vào đây để đọc. Rồi sau khi mở file, thao tác với file thì điều tiếp theo là bạn phải đóng nó lại, điều này sẽ đúng và thực hiện ok một cách ngon lành nếu như không có bất kì 1 ngoại lệ nào được ném ra ngoài. Nhưng cuộc đời thì không phải lúc nào cũng dễ dàng như vậy. Chuyện gì sẽ xảy ra nếu như bạn mở 1 file mà file đó lại không tồn tại ? Và boom!!!, một ngoại lệ được ném ra và câu lệnh inputStream.close(); sẽ không được thực thi. Điều đó đồng nghĩa với việc luống của bạn sẽ không được đóng lại. Và đó là lý do vì sao bạn nên để câu lệnh inputStream.close(); ở khối cuối cùng và sử dụng try-with-resource để đảm bảo rằng kể cả file của bạn có không tồn tại đi nữa thì luồng của bạn chắc chắn vẫn sẽ được đóng lại.

Use a Finally Block

public void closeResourceInFinally() {
  FileInputStream inputStream = null;
  try {
    File file = new File("./tmp.txt");
    inputStream = new FileInputStream(file);
    // use the inputStream to read a file
  } catch (FileNotFoundException e) {
    log.error(e);
  } finally {
    if (inputStream != null) {
      try {
        inputStream.close();
      } catch (IOException e) {
        log.error(e);
      }
    }
  }
}

Như đoạn code bên trên, thì cho dù có bất kì ngoại lệ nào được ném ra thì đoạn code thực thi đóng steam sẽ luôn được thực thi.

The New Try-With-Resource Statement

Một tùy chọn khác là sử dụng try-with-resource, bạn có thể sử dụng chúng khi bạn implements AutoCloseable interface. Đây được coi là một tiêu chuẩn của java. Khi bạn mở resource trong try clause , nó sẽ tự động bị đóng sau khi try block được thực thi hoặc một ngoại lệ được xử lý.

public void automaticallyCloseResource() {
  File file = new File("./tmp.txt");
  try (FileInputStream inputStream = new FileInputStream(file);) {
    // use the inputStream to read a file
  } catch (FileNotFoundException e) {
    log.error(e);
  } catch (IOException e) {
    log.error(e);
  }
}

2. Prefer Specific Exceptions

-Ở mục này thì mình sẽ nói rõ hơn về tầm quan trọng của việc mô tả ngoại lệ

-Việc mô tả ngoại lệ càng chi tiết càng tốt, vì đơn giản là không phải ai cũng biết được code của bạn hoặc có thể là bạn trong vài tháng nữa. Khi ai đó sử dụng hoặc gọi tới hàm của bạn thì việc mô tả chi tiết 1 ngoại lệ mà hàm đó xử lý sẽ giúp tiết kiệm thời gian đọc và tránh những lỗi gặp phải. Do đó hay đảm bảo là bạn đã cung cấp một mô tả chi tiết cho việc này.

  • Một lưu ý nữa là nên tìm 1 class phù hợp nhất cho việc xử lý ngoại lệ của bạn. Ví dụ : ném một NumberFormatException thay vì IllegalArgumentException. Và tránh ném một ngoại lệ Exception.

public void doNotDoThis() throws Exception { ... }
public void doThis() throws NumberFormatException { ... }

3. Document the Exceptions You Specify

-Một cách mô tả nữa là sử dụng java doc

Khi bạn xác định một ngoại lệ trong hàm của bạn, bạn cũng nên ghi lại nó trong Javadoc. Điều nay cũng có mục đích như bên trên, là cung cấp một mô tả chi tiết nhất cho người dùng sau đó để anh ta có thể tránh hoặc xử lý chúng một cách hợp lý. Vì vậy, hãy đảm bảo thêm một khai báo @throw vào Javadoc của bạn và để mô tả các tình huống có thể gây ra ngoại lệ.

/**
  • This method does something extremely useful ... *
  • @param input
  • @throws MyBusinessException if ... happens */ public void doSomething(String input) throws MyBusinessException { ... } `
4\. Throw Exceptions With Descriptive Messages \-Một cách để tăng thêm sự mô tả chi tiết nữa đó là trả về một message cho người dùng gọi hàm của bạn. Và đương nhiên message cũng phải dễ hiểu hoặc đã được mô tả trong tài liệu trước đó. Ví dụ khi gọi 1 API do bạn thiết kế, người dùng truyền vào thiếu 1 param hoặc truyền sai định dạng. Thì việc bạn trả về một message nói rõ đó là param nào và phải truyền như nào cho đúng sẽ dễ dàng hơn cho người dùng khi phải ngồi đoán và tự tìm hiểu xem mình đang sai ở đâu. Nhưng cũng k nên để 1 message quá dài dòng, hay trả về 1 message ngắn gọn nhưng mang đủ ý nghĩa. Không nhưng thế, nó còn làm cho bạn dễ dàng biết là bạn đang gặp phải vấn đề gì và nó nằm ở đâu trong toàn bộ hệ thống. \-Một lưu ý nữa là nếu bạn xử lý và đưa ra 1 ngoại lệ, thì tên của class nó đã mô tả rõ loại lội mà bạn đang gặp phải, vì vậy bạn không cần phải cung cấp thêm nhiều thông tin bôr xung. Một ví dụ điển hình cho điều đó là NumberFormatException. Nó bị ném bởi hàm tạo của lớp java.lang.Long khi bạn cung cấp String ở định dạng sai.
try { new Long("xyz"); } catch (NumberFormatException e) { log.error(e); }

Tên của class NumberFormatException đã mô tả loại lỗi mà bạn gặp phải, việc bây giờ bạn cần là đưa đầu vào khiến gây ra lỗi như dưới đây
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

0

5\. Catch the Most Specific Exception First

\-Hầu hết các IDE bây giờ đều giúp bạn việc bắt một ngoại lệ cụ thể nhất.  
Vấn đề là chỉ có catch block đầu tiên phù hợp với ngoại lệ được thực thi. Vì vậy, nếu bạn bắt gặp IllegalArgumentException trước tiên, bạn sẽ không bao giờ tiếp cận đượccatch block NumberFormatException cụ thể hơn vì nó là một lớp con của IllegalArgumentException.   
Luôn luôn bắt lớp ngoại lệ cụ thể nhất trước tiên và thêm catch blocks ít cụ thể hơn vào cuối danh sách của bạn.

Bạn có thể thấy một ví dụ về câu lệnh try-Catch như vậy trong đoạn code sau. catch block đầu tiên xử lý tất cả các NumberFormatExceptions và catch block thứ hai xử lý tất cả IllegalArgumentExceptions không phải là NumberFormatException.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

1

6\. Don’t Catch Throwable

Throwable là superclass của tất cả các ngoại lệ và lỗi. Bạn có thể sử dụng nó trong một catch clause, nhưng điều này là không khuyến khích.  
Nếu bạn sử dụng throwable, nó sẽ không chỉ bắt được tất cả các ngoại lệ mà nó cũng sẽ bắt tất cả các lỗi. Các lỗi được JVM đưa ra để chỉ ra các vấn đề nghiêm trọng không được xử lý bởi một ứng dụng. Ví dụ điển hình cho điều đó là OutOfMemoryError hoặc StackOverflowError. Cả hai đều được gây ra bởi các tình huống nằm ngoài sự kiểm soát của ứng dụng và có thể xử lý được. Vì vậy, tốt hơn là không nên bắt một Throwable, trừ khi bạn hoàn toàn chắc chắn rằng bạn đã ở trong một tình huống đặc biệt mà bạn có thể hoặc yêu cầu xử lý lỗi.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

2

7\. Don’t Ignore Exceptions

Bạn đã bao giờ phân tích một báo cáo lỗi trong đó chỉ phần đầu tiên của trường hợp sử dụng được thực thi?  
Điều đó thường gây ra bởi một ngoại lệ bị bỏ qua. Nhà phát triển có lẽ khá chắc chắn rằng nó sẽ không bao giờ bị ném và thêm một khối bắt mà không xử lý hay ghi nhật ký.

Và khi bạn tìm thấy block này, rất có thể bạn sẽ tìm thấy một trong những comment nổi tiếng : “This will never happen” 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

3

\-Có phải bạn đang nghĩ là tại sao phải phân tích và xử lý một vấn đề mà nó sẽ không bao giờ xảy ra đúng không ? Nhưng mình xin nhấn mạnh lại là đừng bao giờ bỏ lơ một ngoại lệ. Bạn sẽ không thể chắc chắn rằng trong tương lai đoạn code của bạn sẽ không bị thay đổi, hoặc ai đó có thể làm phá vỡ sự ngăn chặn lỗi xuất hiện. Ít nhất bạn nên viết một thông điệp tường trình nói với mọi người rằng điều không thể tưởng tượng được đã xảy ra và ai đó cần phải kiểm tra nó.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

4

8\. Don’t Log and Throw

Ghi log và throw có lẽ là thực tế tốt nhất thường bị bỏ qua trong danh sách này. Bạn có thể tìm thấy rất nhiều đoạn code và thậm chí các thư viện trong đó một ngoại lệ bị bắt, ghi nhật ký và truy xuất lại. 
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

5

Nó có thể cảm thấy trực quan để ghi lại một ngoại lệ khi nó xảy ra và sau đó suy nghĩ lại để người gọi có thể xử lý nó một cách thích hợp. Nhưng nó sẽ viết nhiều thông báo lỗi cho cùng một ngoại lệ.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line

6

9\. Wrap the Exception Without Consuming It

Nó đôi khi tốt hơn để bắt một ngoại lệ tiêu chuẩn và bọc nó thành một tùy chỉnh.

Một ví dụ điển hình cho một ngoại lệ như vậy là một application hay framework specific business exception. Điều đó cho phép bạn thêm thông tin bổ sung và bạn cũng có thể thực hiện xử lý đặc biệt cho lớp ngoại lệ của mình. Khi bạn làm điều đó, đảm bảo đặt ngoại lệ ban đầu là nguyên nhân. Lớp Exception cung cấp các phương thức xây dựng cụ thể chấp nhận một throwable làm tham số.

Mặt khác, bạn mất stack trace and message của ngoại lệ ban đầu, điều này sẽ gây khó khăn cho việc phân tích sự kiện đặc biệt gây ra ngoại lệ của bạn.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3 at com.company.Main.print4hItemInArray(Main.java:26) at com.company.Main.main(Main.java:13) First line Second line Third line `

7

Tóm Lại

-Như bạn đã thấy, có rất nhiều điều khác nhau bạn nên xem xét khi bạn ném hoặc bắt một ngoại lệ. Hầu hết trong số chúng có mục tiêu cải thiện khả năng đọc code của bạn hoặc khả năng sử dụng API của bạn. -Các ngoại lệ thường là một cơ chế xử lý lỗi và một phương tiện truyền thông tại một thời điểm. -Do đó, bạn nên đảm bảo và thảo luận về các quy tắc tốt nhất về xử lý ngoại lệ Java mà bạn muốn áp dụng với đồng nghiệp để mọi người hiểu các khái niệm chung và sử dụng chúng theo cùng một cách. -Khi sử dụng Retrace APM với code profiling bạn có thể thu thập các ngoại lệ trực tiếp từ Java mà không có bất kỳ thay đổi mã nào!

Bên trên là 9 cách mà mình đã tìm hiểu và tổng hợp lại, rất có thể nó sẽ không hoàn toàn đúng và đầy đủ. Vì vậy rất mong nhận được những lời đánh giá để các bài tiếp theo được hoàn thiện hơn. Cảm ơn mọi người