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 switchcâ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 Integervà 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 Integervì char-> int chuyển nhượng là hợp pháp. (Mọi chargiá 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 Bytevì char-> byte chuyển nhượng KHÔNG hợp pháp. (Hầu hết các chargiá 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 chargiá trị cho một intsau đó hộp intmộ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'để Integerkhô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'để Bytelà 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, Shorthoặ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à 97thậ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 Charactervà sau đó mở rộng Characterra Integervì Characterkhô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.