Tại sao int num = Integer.getInteger (“123”) lại ném NullPointerException?


106

Đoạn mã sau ném NullPointerException:

int num = Integer.getInteger("123");

Trình biên dịch của tôi có đang gọi getIntegernull vì nó tĩnh không? Điều đó không có ý nghĩa gì!

Chuyện gì đang xảy ra vậy?


3
sử dụng Integer.getValue () để thay thế. Bài đăng trên blog này là một giải thích tốt tại sao: konigsberg.blogspot.in/2008/04/…
Pranaysharma

Câu trả lời:


212

Bức tranh lớn

Có hai vấn đề đang diễn ra ở đây:

  • Integer getInteger(String) không làm những gì bạn nghĩ nó làm
    • Nó trả về nulltrong trường hợp này
  • sự phân công từ Integerđến intnguyên nhân tự động unboxing
    • Kể từ khi Integernull, NullPointerExceptionđược ném

Để phân tích (String) "123"để (int) 123, bạn có thể sử dụng ví dụ int Integer.parseInt(String).

Người giới thiệu

Integer Tham chiếu API


Trên Integer.getInteger

Đây là những gì tài liệu nói về những gì phương pháp này thực hiện:

public static Integer getInteger(String nm): Xác định giá trị nguyên của thuộc tính hệ thống với tên được chỉ định. Nếu không có thuộc tính nào có tên được chỉ định, nếu tên được chỉ định trống hoặc nullhoặc nếu thuộc tính không có định dạng số chính xác, thì nullđược trả về.

Nói cách khác, phương thức này không liên quan gì đến việc phân tích cú pháp a Stringthành một int/Integergiá trị, mà đúng hơn, nó liên quan đến System.getPropertyphương thức.

Phải thừa nhận rằng đây có thể là một điều khá bất ngờ. Thật không may khi thư viện có những điều bất ngờ như thế này, nhưng nó dạy cho bạn một bài học quý giá: hãy luôn tra cứu tài liệu để xác nhận những gì một phương pháp thực hiện.

Về cơ bản, một biến thể của vấn đề này đã được giới thiệu trong Return of the Puzzlers: Schlock and Awe (TS-5186) , Josh Bloch và Neal Gafter 2009 Technical Session trình bày. Đây là slide kết luận:

Đạo đức

  • Phương pháp kỳ lạ và khủng khiếp ẩn trong thư viện
    • Một số có tên nghe vô thưởng vô phạt
  • Nếu mã của bạn hoạt động sai
    • Đảm bảo rằng bạn đang gọi đúng phương thức
    • Đọc tài liệu thư viện
  • Đối với nhà thiết kế API
    • Đừng vi phạm nguyên tắc ít ngạc nhiên nhất
    • Không vi phạm phân cấp trừu tượng
    • Không sử dụng các tên tương tự cho các hành vi cực kỳ khác nhau

Để hoàn thiện, cũng có những phương pháp này tương tự như Integer.getInteger:

Câu hỏi liên quan


Trên hộp thư tự động

Tất nhiên, vấn đề khác là làm thế nào để NullPointerExceptionném. Để tập trung vào vấn đề này, chúng ta có thể đơn giản hóa đoạn mã như sau:

Integer someInteger = null;
int num = someInteger; // throws NullPointerException!!!

Đây là trích dẫn từ Phiên bản Java thứ 2 hiệu quả, Mục 49: Ưu tiên các kiểu nguyên thủy hơn các kiểu nguyên thủy đóng hộp:

Tóm lại, ưu tiên sử dụng các nguyên thủy cho nguyên thủy đóng hộp bất cứ khi nào bạn có lựa chọn. Các loại nguyên thủy đơn giản hơn và nhanh hơn. Nếu bạn phải sử dụng nguyên liệu đóng hộp, hãy cẩn thận! Tính năng tự động đóng hộp làm giảm tính dài dòng, nhưng không nguy hiểm, của việc sử dụng các nguyên mẫu đóng hộp. Khi chương trình của bạn so sánh hai nguyên thủy đóng hộp với ==toán tử, nó sẽ thực hiện một so sánh danh tính, điều này gần như chắc chắn không phải là điều bạn muốn. Khi chương trình của bạn thực hiện các phép tính kiểu hỗn hợp liên quan đến các nguyên thủy được đóng hộp và không được đóng hộp, nó sẽ thực hiện việc mở hộp và khi chương trình của bạn thực hiện việc mở hộp, nó có thể ném NullPointerException. Cuối cùng, khi chương trình của bạn đóng hộp các giá trị nguyên thủy, nó có thể dẫn đến việc tạo đối tượng tốn kém và không cần thiết.

Có những nơi bạn không có lựa chọn nào khác ngoài việc sử dụng nguyên liệu đóng hộp, ví dụ như thuốc chung, nhưng nếu không, bạn nên nghiêm túc xem xét nếu quyết định sử dụng nguyên liệu đóng hộp là chính đáng.

Câu hỏi liên quan


11
Vì vậy, Integer.getInteger(s)gần tương đương với Integer.parseInt(System.getProperty(s))? Tôi nghĩ tôi thích cái thứ hai hơn, mặc dù nó dài dòng hơn, vì nó làm nổi bật thực tế là bạn đang lấy thông tin từ các thuộc tính hệ thống.
MatrixFrog

5
Ngay sau khi tôi đăng nhận xét đó, tôi nhận ra rằng tôi chỉ có thể nhìn vào nguồn thực tế của lớp Integer! Tôi đã đi đúng hướng, ngoại trừ việc nó sử dụng Integer.decodethay vì Integer.parseInttìm kiếm đầu 0xhoặc 0để phân tích cú pháp số dưới dạng thập lục phân hoặc bát phân, tương ứng.
MatrixFrog

Đối với những người đang hỏi Tại sao NullPointerException? : programmers.stackexchange.com/questions/158908/…
ROMANIA_engineer

2
@Oracle, bạn có thể không dùng java.lang.Integer.getInteger (String) được không?
mjaggard


6

Vui lòng kiểm tra tài liệu của phương thức getInteger () . Trong phương thức này, Stringtham số là thuộc tính hệ thống xác định giá trị nguyên của thuộc tính hệ thống với tên được chỉ định. "123" không phải là tên của bất kỳ thuộc tính hệ thống nào, như đã thảo luận ở đây . Nếu bạn muốn chuyển đổi Chuỗi này thành int, hãy sử dụng phương thức dưới dạng int num = Integer.parseInt("123").

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.