2009-03-29 34 views
7

tôi stumbled khi một chức năng tìm kiếm như thế này:<?> vs <T>

public void function(Class<?> clazz) {...} 

gì được những ưu/nhược điểm của việc thay đổi phương pháp để:

public <T> void function(Class<T> clazz) {...} 

chỉnh sửa: thời gian biên dịch/thời gian chạy là gì khác biệt.

Trả lời

7

todd.run hoàn toàn đúng, nhưng đó chỉ là một nửa câu trả lời. Cũng có các trường hợp sử dụng để chọn <T> trên <?> (hoặc ngược lại) áp dụng khi bạn không thêm thông số loại vào lớp bao quanh phương thức. Ví dụ, hãy xem xét sự khác biệt giữa

public <E extends JLabel> boolean add(List<E> j) { 
    boolean t = true; 
    for (JLabel b : j) { 
     if (b instanceof JLabel) { 
      t = t && labels.add(b); 
     } 
    } 
    return t; 
} 

public boolean add(List<? extends JLabel> j) { 
    boolean t = true; 
    for (JLabel b : j) { 
     if (b instanceof JLabel) { 
      t = t && labels.add(b); 
     } 
    } 
    return t; 
} 

Phương pháp đầu tiên sẽ thực sự không biên dịch trừ khi bạn thêm một tham số kiểu phù hợp với lớp kèm theo, trong khi phương pháp thứ hai SẼ biên dịch cho dù lớp kèm theo có tham số kiểu. Nếu bạn không sử dụng <?>, thì bạn phải chịu trách nhiệm trước khi nói cho trình biên dịch biết cách lấy loại sẽ được điền vào bằng chữ cái được sử dụng tại chỗ của nó. Bạn thường gặp phải vấn đề này - cần phải sử dụng? thay vì T - khi cố gắng viết các phương thức chung mà sử dụng hoặc cần "mở rộng" và "siêu". Cách xử lý tốt hơn nhưng phức tạp hơn về vấn đề này là ở trang 18 của Gilad Bracha's Generics Tutorial (PDF). Ngoài ra, hãy xem this stack overflow question câu trả lời của họ làm sáng tỏ những vấn đề này.

Kiểm tra liên kết tràn ngăn xếp này để biết thông tin về câu hỏi thứ hai của bạn: Java generics - type erasure - when and what happens. Mặc dù tôi không biết câu trả lời cho câu hỏi của bạn về sự khác biệt về thời gian biên dịch giữa <?><T>, tôi chắc chắn câu trả lời có thể được tìm thấy tại this FAQ mà erickson đã đề cập trong bài đăng đó.

+0

Bạn có thể chụp loại ký tự đại diện trong trường hợp này: boolean add (Danh sách list) {return addImpl (danh sách); } boolean addImpl (danh sách danh sách) {... –

+0

(Mã ví dụ hơi lạ. Bạn có thể trả lại sau khi nhãn.add trả về false. –

+0

Câu trả lời này không có ý nghĩa và không chính xác. Tôi đặt phương thức đầu tiên trong một lớp không có tham số kiểu ('public class test {List labels = new ArrayList (); // add method here}') và nó biên dịch tốt. – user102008

2

Về cơ bản, chúng tương đương nhau. Bạn có thể sử dụng cú pháp đầu tiên mà bạn không cần khai báo bất kỳ thứ gì thuộc loại T.

CẬP NHẬT: oh và T có thể được sử dụng để liên kết các loại với nhau: nếu Class<T> được sử dụng trong các phần khác nhau của hàm sẽ tham chiếu đến cùng một lớp, nhưng không phải là Class<?>.

+0

Tuy nhiên, đó là không đúng trong trường hợp có nhiều lần xuất hiện của / trong một phương pháp chữ ký. – dmeister

+0

Không.Trong trường hợp này là một tham số kiểu phương thức cụ thể, vì vậy nó sẽ không tham chiếu đến cùng loại so với được sử dụng ở cấp lớp, ngay cả khi nó được gọi là T. –

+0

@saua: không ai đang nói về cấp lớp –

10

Sử dụng "?" cũng giống như "bất kỳ", trong khi "T" có nghĩa là "một loại cụ thể". Vì vậy, so sánh các giao diện:

public interface StrictClass<T> { 
public T doFunction(Class<T> class); 
} 

public interface EasyClass<T> { 
public > doFunction(Class<?> class); 
} 

Bây giờ, chúng ta có thể tạo các lớp:

public class MyStrictClass implements StrictClass<String> { 
    public String doFunction(Class<String> stringClass) { 
    //do something here that returns String 
    } 
} 

public class MyEasyClass implements EasyClass<String> { 
    public String doFunction(Class<?> anyClass) { 
    //do something here that returns String 
    } 
} 

Hy vọng rằng sẽ giúp!

+0

"công khai doFunction" là sai và thậm chí không nên biên dịch. Tôi cho rằng bạn có nghĩa là nó là "public T doFunction". –

+0

Ngoài ra, "lớp" không thể được sử dụng như một tên biến, bởi vì nó là một từ dành riêng. –

0

Tài nguyên tốt có thể là: http://sites.google.com/site/io/effective-java-reloaded Phần thú vị liên quan đến câu hỏi của bạn bắt đầu vào khoảng phút thứ 5. Chỉ cần nghiện những gì người dùng trước đó đã nói.

Hy vọng rằng sẽ giúp:]

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