2016-07-18 17 views
5

Giả sử tôi có một Parcel lớp chung và một phương thức phân phối chung được hiển thị trong mã bên dưới. Phương thức in và trả về x được gán một tham số kiểu Integer bên trong phương thức.Không gõ tham số đóng vai trò nào?

public class Parcel<T> { 
    public <X> X deliver(){ 
     X x = (X) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

Bên trong chính tôi gọi phương thức được phân phối bằng cách chuyển thông số loại Parcel. Tuy nhiên, nó vẫn in 100.

public static void main(String args[]) { 
    Parcel<String> parcel = new Parcel<>(); 
    System.out.println(parcel.<Parcel> deliver()); 
} 

Điều này theo sau đối số loại Parcel được truyền trong dòng in không đóng bất kỳ vai trò nào và tôi dự kiến ​​có ngoại lệ tại đây. Làm thế nào nó hoạt động ?

+5

Vì bạn đang ràng buộc với 'java.lang.Object'. 'X' không bị ràng buộc với bất kỳ kiểu cụ thể nào giả định rằng nó là ràng buộc trên là' java.lang.Object', vì vậy không có 'ClassCastException'. Bạn sẽ nhận được một, nếu bạn gọi 'deliver' và đưa kết quả vào một biến/field/parameter có các kiểu khác với' java.lang.Object', 'java.lang.Number' và' java.lang. Số nguyên'. Và mã của bạn không thành công vì bạn gọi 'println (Object)'. Nếu bạn thay đổi nó thành 'bưu kiện. cung cấp() ', trình biên dịch sẽ sử dụng' println (String) 'sẽ dẫn đến' java.lang.Integer không thể được đúc thành java.lang.String' –

+1

Ngoài ra, bạn có thể thay đổi ràng buộc '' của bạn thành một loại bê tông, và trình biên dịch sẽ sử dụng phép đúc kiểu conrete trong phương thức 'deliver()' của bạn. Nói, '' sẽ dẫn đến 'ClassCastException' cho dòng này:' X x = (X) (Object) new Integer (100); 'vì' X' được thay thế bằng 'java.lang.String' đây. –

Trả lời

1

Những gì bạn quan sát được gọi là type erasure. Các tham số chung được sử dụng bởi trình biên dịch để đảm bảo tính chính xác của loại và không có trong thời gian chạy.

Nói chung không có gì dừng bạn làm thủ thuật này:

List<Integer> list = new ArrayList<>(); 
list.append(""); // produces compiler error 

// just drop that "useless" generic argument 
List erased = (List) list; 
erased.append(""); // works fine 

EDIT

Thực ra câu trả lời ban đầu của tôi thỉnh thoảng bị cho Parcel thi này

public class Parcel<T> { 
    public T deliver(){ 
     T x = (T) new Integer(100); 
     System.out.println(x); 
     return x; 
    } 
} 

Nhưng ý tưởng quan trọng là tương tự cho <X> X deliver():

Object parcel = parcel.<Parcel> deliver(); // erased, works ok 
Parcel parcel = parcel.<Parcel> deliver(); // java.lang.ClassCastException 
Các vấn đề liên quan