2010-05-06 8 views
13

Một Java gọi phương thức có thể được tham số như trong đoạn mã sau:Khi nào một cuộc gọi phương thức tham số có ích?

class Test 
{ 
    <T> void test() 
    { 
    } 

    public static void main(String[] args) 
    { 
     new Test().<Object>test(); 
     //   ^^^^^^^^ 
    } 
} 

tôi phát hiện ra đây là có thể từ hộp thoại thiết lập Eclipse Java Formatter và tự hỏi nếu có bất kỳ trường hợp này rất hữu ích hoặc theo yêu cầu.


EDIT

Dựa trên câu trả lời tuyệt vời Arne của tôi đã đưa ra kết luận sau:

Ngoài cải thiện an toàn kiểu như ví dụ Arne của minh họa một phương pháp gọi tham số cho phép bạn chỉ định các loại cơ sở chung của các đối số phương thức phải là loại phần tử vùng chứa. Kiểu này thường được biên dịch tự động bởi trình biên dịch với kiểu cơ sở chung cụ thể nhất. Bằng cách tham số hóa phương thức gọi hành vi này có thể bị ghi đè. Một cuộc gọi phương thức tham số có thể được yêu cầu nếu có nhiều kiểu phổ biến bị trình biên dịch suy luận.

Ví dụ sau đây cho thấy hành vi đó:

import java.util.Arrays; 
import java.util.List; 

class Test 
{ 
    public static void main(String[] args) 
    { 
     Integer a=new Integer(0); 
     Long b=new Long(0); 
     List<Object> listError=Arrays.asList(a, b); 
     //error because Number&Comparable<?> is not Object 
     List<Object> listObj=Arrays.<Object>asList(a, b); 
     List<Number> listNum=Arrays.<Number>asList(a, b); 
     List<Comparable<?>> listCmp=Arrays.<Comparable<?>>asList(a, b); 
    } 
} 

Hành vi này được định nghĩa trong Java Language Specification Third Edition đoạn 8.4.4 và 15.12.2.7 nhưng không dễ hiểu.

+0

chỉ là nó với tôi rằng nghĩ đó là lạ thế nào tất cả mọi người trong chủ đề này dường như nghĩ rằng một "phương pháp tham số" phải là một phương pháp chung chung? Phương thức có tham số được khai báo là phương thức "được tham số hóa". Một phương thức chung chung chỉ là một phương thức được tham số hóa khác, trong đó kiểu là một tham số như vậy. Hay tôi đã bỏ lỡ điều gì đó? –

+0

Bạn đang phát hiện! Trong tầm nhìn, tiêu đề có thể đã là "Khi nào một phương thức gọi với các đối số kiểu mà không thể suy ra hữu ích?" –

Trả lời

13

Tôi không bao giờ đã sử dụng này trong thực tế, nhưng bạn có thể tưởng tượng được sử dụng điều này cho loại an toàn.Hãy xem xét các phương pháp sau đây:

<T> void method(T... items) { 
    List<T> list = new ArrayList<T>(); 
    for (T item : items) 
     list.add(item); 
    System.out.println(list); 
} 

Bạn có thể gọi nó theo cách này:

o.<Object>method("Blah", new Long(0)); 
o.<Number>method(new Integer(100), new Long(0)); 

Nhưng điều này sẽ nâng cao một lỗi biên dịch:

o.<Number>method("String", new Long(0)); 

Vì vậy, bạn có một phương pháp chung đó là typesafe và có thể được sử dụng cho mọi đối tượng, không giới hạn đối với giao diện hoặc lớp paricular.

+0

câu trả lời tuyệt vời đặc biệt là việc sử dụng varargs –

8

Nó có lẽ hữu ích nhất khi bạn đang lấy một bộ sưu tập của một số loại, và trả lại một số tập hợp con của bộ sưu tập đó.

<T> List<T> filter(Collection<? extends T> coll, Predicate<? super T> pred) { 
    List<T> returnList = new ArrayList<T>(); 
    for(T t : coll) { 
     if(pred.matches(t)){ 
      returnList.add(t); 
     } 
    } 
    return returnList; 
} 

Edit:

Tổng quát hơn, nó rất hữu ích khi bạn muốn trả về một loại hình cụ thể, hoặc bạn muốn liên kết các loại của hai hay nhiều thông số một cách tổng quát.

+1

bạn không thực hiện cuộc gọi phương thức tham số ở bất kỳ đâu trong mã đó – newacct

13

Các cuộc gọi phương thức tham số hữu ích khi bạn muốn cho phép các loại khác nhau mà không cần truyền. Ví dụ, lớp trợ giúp Collections sử dụng rộng rãi các cuộc gọi phương thức được tham số hóa. Khi bạn muốn thực hiện một bộ sưu tập chung mới sử dụng một trong những phương pháp helper của họ, một vài ví dụ:

List<String> anEmptyStringList = Collections.<String>emptyList(); 
Set<Integer> unmodifiableCopy = Collections.<Integer>unmodifiableSet(originalSet); 

Vì vậy, khi bạn muốn để có thể sử dụng các loại generic nơi khác, bạn muốn sử dụng những phương thức gọi. Chúng ngăn chặn các cảnh báo trình biên dịch khi sử dụng Generics.

+1

Không phải kiểu thu thập được suy ra từ khai báo biến không? –

+0

Bạn sẽ nhận được một cảnh báo diễn xuất từ ​​trình biên dịch (trừ khi bạn đã tắt chúng) nếu bạn thực hiện 'List anEmptyStringList = Collections.emptyList()' mà không có tham số trong cuộc gọi. Trong thực tế, lần đầu tiên tôi đã học được điều này từ một đồng nghiệp đã chỉ cho tôi cách loại bỏ cảnh báo. – justkt

+0

Tôi không thể tạo lại cảnh báo đó trên thiết lập của mình. Không, ngay cả với tham số -Xlint. Đó có thể là do sự khác biệt của trình biên dịch. Tôi sử dụng javac 1.6.0_20 từ Sun JDK trên Linux. –

1

Ví dụ, khi bạn cần một số phương pháp phổ biến để so sánh:

public static <T extends Comparable> T max(T one, T two) { 
    if (one.compareTo(two) > 0) { 
     return one; 
    } else { 
     return two; 
    } 
} 
+1

Giả sử phương thức là thành viên của lớp Aggregator và tham số kiểu chung T được thêm vào Comparable trong khai báo thì tôi có thể gọi nó đơn giản là Aggregator.max (new Integer (5), new Integer (10)); Không có thông số cần thiết cho cuộc gọi. –

+0

bạn không thực hiện cuộc gọi phương thức tham số ở bất kỳ đâu trong mã đó – newacct

+0

Đúng, đồng ý. Không cần phải chỉ định thêm lớp. –