2017-02-09 22 views
10
public static <T> T foo(T x, T x2) { 
    return (T) (x + " " + x2); 
} 

public static void main(String args[]) { 
    System.out.println(foo(33, "232")); 
} 

Tôi biết T là loại được chuyển trong tham số. Nhưng ở đây có hai loại. Cái nào trong số đó là T?Tại sao mã chung này trong biên dịch java?

và tại sao trình biên dịch không bắt buộc tôi phải có các thông số cùng loại khi tôi gọi foo?

+12

Đó là hợp pháp vì 'T' có thể là' Đối tượng', vì vậy bạn có thể chuyển phương thức cho bất kỳ hai đối tượng nào. ('32' có thể là' Số nguyên' thay vì 'int' trong trường hợp này.) – khelwood

+1

Và giới hạn trên của' T' là 'Đối tượng', vì vậy trong mã được biên dịch, ký tự' (T) 'là' (Object) ', là hợp lệ, bởi vì' String' là một 'Object'. –

+1

Ngoài ra để thêm vào các ý kiến, đó là lý do tại sao bạn không bao giờ muốn sử dụng các loại undbound (để lại các generics), như cơ bản mọi sự kết hợp của các lớp là hợp lệ do nó. Khi bạn làm điều đó, bạn có thể thấy mình trong một sitatation, nơi 'ClassCastExceptions' là kết quả bình thường khi cố gắng làm việc với các kiểu thô – SomeJavaGuy

Trả lời

16

Đó là hợp pháp vì IntegerString có loại cơ sở chung. T có thể là Object, vì vậy foo(T, T) sẽ chấp nhận bất kỳ hai đối tượng nào. 32 có thể được tự động lưu vào một số Integer, là một loại Object. "232"String, là một loại Object.

(Như đã chỉ ra bởi ý kiến, cho IntegerString, có một cơ sở-loại phổ biến gần hơn, Serializable;. Nhưng nguyên tắc là như nhau bất cứ cơ sở gõ biên dịch giải quyết T đến)

+0

Bạn có thể mô tả những gì xảy ra trong dòng này: 'return (T) (x +" "+ x2)'? Nó có tương đương với 'return (Object) (x.toString() +" "+ x2.toString())'?Nếu vậy, điều gì sẽ xảy ra trong quá trình truyền, nếu nó diễn ra một chuỗi để phản đối thì chuỗi này được lấy ra như thế nào trong quá trình in? – TheLogicGuy

+1

@TheLogicGuy Nếu bạn thử và thêm bất kỳ đối tượng nào vào một chuỗi, nó sẽ được chuyển đổi bằng cách sử dụng 'toString()'. Nếu bạn thử và in bất kỳ đối tượng nào, nó sẽ chuyển đổi được chuyển đổi thành một String bằng cách sử dụng 'toString()'. (Nếu đối tượng của bạn là một chuỗi, 'toString()' chỉ trả về 'this'.) – khelwood

5
public static <T> T foo(T x, T x2) { 
    return (T) (x + " " + x2); 
} 

cần lưu ý rằng trong khi biên dịch này, nó có thể thất bại trong thời gian chạy:

int f = foo(1, 2); 

sẽ thất bại Ideone demo, bởi vì phương pháp này trả về một String, không phải là một 0.123..

biên dịch, tuy nhiên, vì xóa kiểu có nghĩa là T được viết lại theo giới hạn trên, cụ thể là Object. Vì vậy:

public static Object foo(Object x, Object x2) { 
    return (Object) (x + " " + x2); 
} 

Điều này là tốt, bởi vì kết quả là một String, mà là một subtype của Object.

Tôi đoán đây chỉ là một trường hợp mà các mô hình generics nó chờ đợi để bắt bạn ra ngoài. Đây là lý do tại sao tôi sẽ tránh pha trộn generics và đúc rõ ràng.

+1

int f = foo (1, 2); sẽ không biên dịch .. – Brovoker

+0

@Brovoker tại sao không? –

+0

Vì không có cá thể biến kiểu tồn tại để T tuân theo int – Brovoker

Các vấn đề liên quan