public class Test {
public static class Nested<T> {
public T val;
Nested(T val) { this.val = val; }
}
public static void main(String[] args) {
Nested<Integer> a = new Nested<Integer>(5);
Nested<Integer> b = new Nested<Integer>(2);
Integer diff = a.val - b.val;
}
}
Mã trên hoạt động tốt. Tuy nhiên, nếu tôi thêm một phương pháp để lồng nhau:Tại sao loại xóa của Java không phá vỡ điều này?
T diff(Nested<T> other) { return this.val - other.val; }
tôi nhận được một lỗi biên dịch:
operator - cannot be applied to T,T
Điều này làm cho ý nghĩa với tôi. Kiểu T bị xóa khi chạy, vì vậy Java không thể áp dụng toán tử chỉ được định nghĩa cho các lớp nhất định như Integer. Nhưng tại sao a.val - b.val
hoạt động?
Chỉnh sửa:
Rất nhiều câu trả lời hay. Cảm ơn mọi người. Các ý chính của nó, nếu tôi hiểu chính xác, là trình biên dịch có thể thêm phôi vào số nguyên trong a.val - b.val
vì nó biết a
và b
được khởi tạo là Nested
. Tuy nhiên, kể từ khi <Integer
>this.val - other.val
xảy ra bên trong cơ thể của một định nghĩa hàm chung (trong đó T vẫn có thể là bất cứ điều gì), trình biên dịch không thể thêm các phôi cần thiết để thực hiện công việc "-
". Điều này dẫn đến một câu hỏi thú vị hơn, cụ thể là, nếu trình biên dịch Java có khả năng inlining, nó sẽ có thể cho một hàm chung như diff để làm việc?
Kiểu 'a.val' được biết tại thời gian biên dịch thành' Số nguyên' trong trường hợp đầu tiên, nhưng chỉ 'T' trong trường hợp thứ hai. Trong trường hợp thứ hai, hãy xem xét điều gì xảy ra nếu một mô đun khác khởi tạo 'Test.Nested' cho một số lớp 'Foo'. –
nneonneo
Cụ thể, trình biên dịch chèn một '(Integer)' cast ở phía trước của các biểu thức 'a.val' và' b.val'. Đây là những gì generics làm. –