Các lý do khá phức tạp, nhưng tất cả đều nằm trong chi tiết ( bản in đẹp nếu bạn muốn) của Đặc tả ngôn ngữ Java.
Đầu tiên, JLS 14.11 nói như sau về các switch
câu lệnh:
"Mọi hằng số trường hợp liên quan đến câu lệnh chuyển đổi phải được gán tương thích với loại Biểu thức của câu lệnh chuyển đổi ( §5.2 )."
Điều này có nghĩa là 'a'
cần phải được gán Integer
và Byte
tương ứng.
Nhưng điều đó không đúng:
Bạn sẽ nghĩ rằng vì 'a'
nên được gán cho một Integer
vì char
-> int
chuyển nhượng là hợp pháp. (Mọi char
giá trị sẽ phù hợp với một int
.)
Bạn sẽ nghĩ rằng vì 'a'
KHÔNG nên được gán cho một Byte
vì char
-> byte
chuyển nhượng KHÔNG hợp pháp. (Hầu hết các char
giá trị sẽ không vừa với một byte.)
Trong thực tế, cả hai điều này đều không đúng. Để hiểu lý do tại sao, chúng ta cần đọc JLS 5.2 thực sự về những gì được phép trong bối cảnh chuyển nhượng.
"Bối cảnh chuyển nhượng cho phép sử dụng một trong những điều sau đây :
- chuyển đổi nhận dạng (§5.1.1)
- một chuyển đổi nguyên thủy mở rộng (§5.1.2)
- chuyển đổi tham chiếu mở rộng (§5.1.5)
- chuyển đổi tham chiếu mở rộng theo sau là chuyển đổi unboxing
- một chuyển đổi tham chiếu mở rộng theo sau là một chuyển đổi unboxing, sau đó là một chuyển đổi nguyên thủy mở rộng
- chuyển đổi quyền anh (§5.1.7)
- một chuyển đổi quyền anh theo sau là một chuyển đổi tham chiếu mở rộng
- một chuyển đổi unboxing (§5.1.8)
- một chuyển đổi unboxing theo sau là một chuyển đổi nguyên thủy mở rộng. "
Để đi từ 'a'
đến Integer
, chúng tôi sẽ cần phải 1 mở rộng char
giá trị cho một int
sau đó hộp int
một Integer
. Nhưng nếu bạn xem xét các kết hợp chuyển đổi được phép, bạn không thể thực hiện chuyển đổi nguyên thủy mở rộng theo sau là chuyển đổi quyền anh.
Do đó 'a'
để Integer
không được phép. Điều này giải thích lỗi biên dịch trong trường hợp đầu tiên.
Bạn sẽ nghĩ rằng 'a'
để Byte
là không được phép vì đó sẽ bao gồm một chuyển đổi thu hẹp nguyên thủy ... mà không có trong danh sách ở tất cả. Trong thực tế, nghĩa đen là một trường hợp đặc biệt. JLS 5.2 tiếp tục nói như sau.
"Ngoài ra, nếu biểu thức là biểu thức không đổi ( §15.28 ) của kiểu byte, short, char hoặc int:
Một chuyển đổi nguyên thủy thu hẹp có thể được sử dụng nếu biến có kiểu byte, ngắn hoặc char và giá trị của biểu thức hằng được biểu diễn trong loại biến.
Chuyển đổi nguyên thủy thu hẹp theo sau là một chuyển đổi quyền anh có thể được sử dụng nếu biến là loại Byte
, Short
hoặc Character
, và giá trị của biểu thức liên tục được biểu diễn trong các loại byte, short, hoặc char tương ứng."
Thứ hai trong số này áp dụng 'a'
cho Byte
, bởi vì:
- một ký tự là một biểu thức không đổi, và
- giá trị
'a'
là 97
thập phân, nằm trong phạm vi cho byte
( -128
đến +127
).
Điều này giải thích tại sao không có lỗi biên dịch trong ví dụ thứ hai.
1 - Chúng tôi không thể mở rộng thành 'a'
một Character
và sau đó mở rộng Character
ra Integer
vì Character
không phải là một kiểu con của Java Integer
. Bạn chỉ có thể sử dụng chuyển đổi tham chiếu mở rộng nếu loại nguồn là kiểu con của loại mục tiêu.