Hành vi kỳ lạ của Java khi gán giá trị. Java đang làm gì đằng sau hậu trường để điều này xảy ra?


10

Vài ngày trước, tôi đã gặp một kịch bản hấp dẫn mà tôi không thể tìm thấy bất kỳ tài liệu nào về cách thức hoặc lý do Java cho phép điều sau xảy ra. (Đoạn mã này chỉ là một hình thức đơn giản của lỗi.)

    @Test
    public void test() {
      boolean bool = false;
      Integer intVal = Integer.valueOf(5);
      Long longVal = null;
      Long result = bool ? intVal : longVal;

      System.out.println(" > " + result);
   }

trong đoạn trích trên:

nếu bool = true, thì bạn nhận được giá trị '5';

nhưng nếu bool = false, thì bạn sẽ có một ngoại lệ con trỏ null khi cố gắng đánh giá hoạt động ternary. KHÔNG phải là tuyên bố in.


Để sửa lỗi này, tôi chỉ cần thay đổi 'kết quả' thành

Long result = bool ? Long.valueOf(intVal) : longVal;

Làm điều này, sẽ đưa ra hành vi dự kiến ​​tôi cần:

nếu bool = true, thì bạn nhận được giá trị '5';

nhưng nếu bool = false, thì bạn nhận được 'null'


Bây giờ phần thú vị là nếu bạn chia nó thành một câu lệnh if / other bình thường, thì java KHÔNG cho phép bạn biên dịch

longVal = intVal; 

nhưng nó không nắm bắt được điều đó thông qua toán tử ternary. Vậy Java đang làm gì để biến nó thành điểm không trong đoạn trích gốc?

(java 11)

Câu trả lời:


10

Khi bạn làm điều này:

Long result = bool ? intVal : longVal

Biểu thức này đang trả về a longvà khi boolsai, nó cố gắng bỏ hộp nullđến giá trị Long để khớp với resultbiến và ném NPE.

Khi bạn làm điều này:

Long result = bool ? Long.valueOf(intVal) : longVal

Biểu thức này đã trở lại Longsau đó không cần hủy hộp và nullgiá trị được gán thành công choresult biến.

Tài liệu tham khảo:

Như đã thảo luận trong phần bình luận, để hiểu rõ hơn tại sao điều này xảy ra, hãy kiểm tra các phần sau của JLS:


Tôi ngạc nhiên khi bạn tham khảo bảng tham chiếu khác nhau 15,25 A đến E trong đó "rõ ràng" rằng Số nguyên / Dài dẫn đến một bnp (Số nguyên, Dài).
matt

Câu trả lời tốt. Nói chung khi tôi hoàn toàn không có ý tưởng gì, những gì đang diễn ra bên trong, tôi khuyên bạn nên xem qua mã byte được biên dịch, cho thấy gần như chính xác, những gì được mô tả. Ít nhất là khi trích xuất một đoạn mã tối thiểu, đó ít nhiều là vấn đề đào tạo, cách đọc và hiểu nó.
Jan Held

Như JLS, Mục 5.6.2 nói: "Nếu bất kỳ toán hạng nào thuộc loại tham chiếu, thì nó phải chịu chuyển đổi unboxing"; sau đó "Mở rộng chuyển đổi nguyên thủy (§5.1.2) được áp dụng [..]"
Diego Magdaleno
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.