2012-04-13 33 views
5

Tôi có phương thức lấy một đối số là List<?>.Đối số loại chung Java

public static String method(List<?> arg){ 
    // Do something based on type of the list 
} 

//I call the method as below 
List<ClassA> listA = new ArrayList<ClassA>(); 
List<ClassB> listB = new ArrayList<ClassB>(); 
method(listA); 
method(listB); 

Trong method, làm thế nào để tôi biết nếu arg là một List của ClassA hoặc một List của ClassB?

+2

Khai báo kiểu tham số là '' có nghĩa là bạn không quan tâm đến loại thực tế. – biziclop

+0

trùng lặp với http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list – evanwong

+0

@evanwong này - không chắc chắn liệu tôi có đồng ý một bản dupe hay không. – djangofan

Trả lời

3

Từ câu trả lời của người dùng được gọi là Romain "Nếu bạn sử dụng <?>, Bạn có nghĩa là bạn sẽ không sử dụng loại parametrized ở bất kỳ nơi nào. Ngoài ra, tôi tin rằng nếu bạn sử dụng câu hỏi đánh dấu trình biên dịch sẽ không bắt loại không phù hợp cho đến khi chạy (được sửa lại; p.119 của Java hiệu dụng), bỏ qua xóa, và hiệu quả loại bỏ lợi ích bạn nhận được từ việc sử dụng các loại chung loại ???

Để trả lời câu hỏi của người hỏi: nếu bạn sử dụng Danh sách < Đối tượng> và sau đó thử truyền đến A hoặc B, có thể sử dụng instanceOf, đó có thể là cách để biết đó là gì. Tôi đặt cược có một cách tốt hơn để làm điều đó hơn mặc dù.

+1

+1 cho OP là _effectively loại bỏ lợi ích bạn nhận được từ việc sử dụng loại generic_ – jahroy

+1

có nghĩa là "Tôi không sử dụng Generics nhưng tôi muốn thoát khỏi cảnh báo trình biên dịch." – user949300

+3

-1 vì câu trả lời này khuyến khích thực hành mã hóa kém. Việc xác định một phương thức lấy một đối số kiểu chung là cách thích hợp để làm điều này - nó mang lại cho bạn sự an toàn về kiểu và không đòi hỏi quá trình đúc lộn xộn. Xem câu trả lời của jahroy. –

1

Ví dụ của bạn, không có cách nào để biết đối số kiểu chung cho List là gì. Chúng bị xóa ở cấp độ cá thể.

14

Về mặt kỹ thuật, bạn CAN sử dụng instanceof để kiểm tra xem một đối tượng là một loại nhất định.

Tuy nhiên ... Đó là NOT là một ý tưởng hay.

Cách bạn đã tuyên bố phương pháp của bạn, nó có thể chấp nhận một danh sách của bất kỳ loại, vì vậy nó không nhất thiết sẽ là A hoặc B.

Thật khó để biết những gì bạn đang cố gắng làm , nhưng bạn có lẽ nên làm cho phương pháp của bạn chung chung.

Bạn có thể làm như vậy như thế này:

public static <T> String method(List<T> arg) { 
    // We now know that the type of the list is T, which is 
    // determined based on the type of list passed to this 
    // method. This would demonstrate the point better if 
    // the return type was T, but I'm leaving the return type 
    // as String, because that's what your code returns. 
} 

Dưới đây là một ví dụ tốt hơn:

Nếu bạn muốn tạo ra một phương pháp chung mà trả về phần tử đầu tiên của danh sách, bạn sẽ làm như sau:

public static <T> T firstElement(List<T> theList) { 
    if (theList == null) { 
     return null; 
    } 
    T objectOfTypeT = theList.get(0); 
    return objectOfTypeT; 
} 

Lưu ý rằng lợi tức loại hiện là T.

Bởi vì chúng tôi đã thực hiện phương pháp này chung chung, nó có thể trả về cùng một loại được sử dụng trong Danh sách.

Bạn thường chỉ trả lại theList.get(0), nhưng tôi đã thêm một dòng để làm cho mục đích của generics rõ ràng hơn.

Giải thích về cú pháp:

  • Các <T> chỉ ra rằng phương pháp này có một số loại tên T.

  • Các T rằng ngay sau là kiểu trả về (giống như bạn bình thường Chuỗi trả về, Số nguyên, v.v ...).

  • Số T trong thông số Danh sách là cách trình biên dịch biết số h2 là T là gì.

này cho phép trình biên dịch để nói: "Phương pháp này hy vọng một cái gì đó kiểu T. Oh nhìn ... Danh sách này cũng là kiểu T. Nếu ai đó đi qua một danh sách các Strings để phương pháp này, hơn T phải là một string. Nếu ai đó đi qua một danh sách các số nguyên để phương pháp này, T phải là một Integer. "

Ngược lại, phương pháp của bạn có thể chỉ trả về một string và nó không có ý tưởng gì loại được sử dụng trong danh sách.


Cũng ...

Nếu A và B đều mở rộng các lớp tương tự, tên TheParentClass, bạn có thể khai báo các phương pháp của bạn như thế này:

public static String method(List<? extends TheParentClass> arg) 

Bằng cách đó, bạn sẽ biết nhiều hơn một chút về các loại tham số có thể của bạn (và có thể hưởng lợi từ việc kiểm tra kiểu thời gian biên dịch).

+0

Ví dụ cuối cùng mà bạn đưa ra là "? Mở rộng TheParentClass" có lẽ là như thế nào? "có nghĩa" được sử dụng. Cho phép sử dụng a? mà không có chút mở rộng, như David Mason gợi ý, thực hành xấu nhưng hợp pháp. Tôi nghĩ rằng jahroy nên được trao giải đáp cho câu hỏi này chứ không phải là tôi vì anh ấy đã đóng đinh nó. – djangofan

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