2013-08-07 11 views
26

Cuối cùng tôi thử nghiệm với generics một chút. Tôi đã đưa ra đoạn mã này:Java: Thử nghiệm với generics

public class Test { 

    static <T> void f(T x) { 
     x = (T) (Integer) 1234; 
     System.out.println(x); 
    } 

    public static void main(String[] args) { 
     f("a"); 
     f(1); 
     f('a'); 
     f(1.5); 
     f(new LinkedList<String>()); 
     f(new HashMap<String, String>()); 
    } 
} 

Tôi chạy này và nhận được kết quả này:

1234 
1234 
1234 
1234 
1234 
1234 

không có ngoại lệ! Làm thế nào là nó có thể?

+0

Hãy cẩn thận - bạn đang đi lạc nguy hiểm khi hỏi: "Tại sao các generics không hoạt động như các mẫu C++?" –

Trả lời

36

Đó là vì type erasure (rất nhiều đã được viết về điều này, chỉ cần google cho thuật ngữ này). Sau khi biên soạn f mã byte phương pháp này có thể trông như thế này:

static void f(Object x) { 
    x = (Object) (Integer) 1234; 
    System.out.println(x); 
} 

Vì vậy System.out.println sẽ chỉ gọi phương thức trên đối tượng toStringx - và trong trường hợp của bạn nó là Integer.toString().

+1

thats một câu trả lời tuyệt vời :) –

3

Vì loại xóa. Từ Oracle's documentation:

Generics đã được giới thiệu về ngôn ngữ Java để cung cấp loại chặt chẽ kiểm tra tại thời gian biên dịch và hỗ trợ lập trình generic. Để thực hiện Generics, trình biên dịch Java áp dụng loại tẩy xoá để:

  • Thay thế tất cả các thông số loại trong các loại generic với giới hạn của họ hoặc Object nếu các thông số loại là vô biên. Bytecode được sản xuất, do đó, chỉ chứa các lớp, giao diện và phương thức thông thường.

  • Chèn phôi loại nếu cần để bảo toàn an toàn loại.

  • Tạo các phương thức cầu để bảo tồn đa hình trong các loại chung mở rộng.

Loại tẩy xóa đảm bảo không tạo lớp mới cho tham số loại; do đó, generics không phải chịu chi phí thời gian chạy.

+3

Khi bạn sao chép các từ của một nguồn lực bên ngoài, luôn luôn đảm bảo bạn báo giá đúng và liên kết từ ngữ gốc. –