Điều đầu tiên cần ghi nhớ là các toán tử ternary Java có "kiểu" và đây là điều mà trình biên dịch sẽ xác định và xem xét bất kể loại thực tế / thực của tham số thứ hai hoặc thứ ba là gì. Tùy thuộc vào một số yếu tố, loại toán tử ternary được xác định theo các cách khác nhau như được minh họa trong Đặc tả ngôn ngữ Java 15,26
Trong câu hỏi trên chúng ta nên xem xét trường hợp cuối cùng:
Mặt khác, các toán hạng thứ hai và thứ ba có kiểu S1 và S2 tương ứng. Đặt T1 là loại kết quả từ việc áp dụng chuyển đổi quyền anh thành S1 và để T2 là loại kết quả từ việc áp dụng chuyển đổi quyền anh sang S2 . Loại biểu thức điều kiện là kết quả của việc áp dụng chuyển đổi chụp (§5.1.10) sang mỡ (T1, T2) (§15.12.2.7).
Đây là trường hợp phức tạp nhất một khi bạn xem xét áp dụng chuyển đổi chụp (§5.1.10) và hầu hết tất cả tại Lub (T1, T2) .
Bằng tiếng Anh đơn giản và sau khi đơn giản hóa cực độ, chúng ta có thể mô tả quá trình tính toán "Siêu lớp chung nhỏ nhất" (vâng, nghĩ về LCM) của các tham số thứ hai và thứ ba. Điều này sẽ cung cấp cho chúng tôi "loại" toán tử ternary. Một lần nữa, những gì tôi vừa nói là một sự đơn giản hóa cực độ (xem xét các lớp thực hiện nhiều giao diện phổ biến).
Ví dụ: nếu bạn thử như sau:
long millis = System.currentTimeMillis();
return(true ? new java.sql.Timestamp(millis) : new java.sql.Time(millis));
Bạn sẽ nhận thấy rằng loại kết quả của biểu thức điều kiện là java.util.Date
vì nó là "Siêu lớp chung tối thiểu" cho cặp Timestamp
/ Time
.
Vì null
có thể được hộp tự động cho bất cứ thứ gì, "Siêu lớp chung nhỏ nhất" là Integer
lớp và đây sẽ là kiểu trả về của biểu thức điều kiện (toán tử ternary) ở trên. Giá trị trả về sau đó sẽ là một con trỏ rỗng loại Integer
và đó là giá trị sẽ được trả về bởi toán tử ternary.
Trong thời gian chạy, khi Máy ảo Java bỏ hộp thì Integer
a NullPointerException
bị ném. Điều này xảy ra bởi vì JVM cố gắng gọi hàm null.intValue()
, null
kết quả của việc tự động đóng hộp.
Theo ý kiến của tôi (và vì ý kiến của tôi không nằm trong Đặc tả ngôn ngữ Java, nhiều người sẽ thấy nó không đúng), trình biên dịch thực hiện công việc kém trong việc đánh giá biểu thức trong câu hỏi của bạn. Cho rằng bạn đã viết true ? param1 : param2
trình biên dịch nên xác định ngay rằng tham số đầu tiên - null
- sẽ được trả về và nó sẽ tạo ra lỗi trình biên dịch. Điều này hơi giống với khi bạn viết while(true){} etc...
và trình biên dịch phàn nàn về mã bên dưới vòng lặp và gắn cờ với nó Unreachable Statements
.
Trường hợp thứ hai của bạn khá đơn giản và câu trả lời này đã quá dài ...;)
ĐIỀU CHỈNH:
Sau một phân tích khác, tôi tin rằng tôi đã sai khi nói rằng một null
giá trị có thể được đóng hộp / tự động đóng hộp vào bất cứ thứ gì. Nói về lớp Integer, quyền anh rõ ràng bao gồm việc gọi hàm new Integer(...)
tạo hoặc có thể Integer.valueOf(int i);
(tôi tìm thấy phiên bản này ở đâu đó). Cái trước sẽ ném một NumberFormatException
(và điều này không xảy ra) trong khi cái thứ hai sẽ không có ý nghĩa vì int
không thể null
...
int foo = (true ? null : 0)
vànew Integer(null)
cả hai đều biên dịch tốt, thứ hai là hình thức tự động rõ ràng.