2008-08-24 43 views
19

tôi đã xác định một hàm Java:Tại sao tôi không thể chuyển một cách rõ ràng đối số kiểu cho một phương thức Java chung?

static <T> List<T> createEmptyList() { 
    return new ArrayList<T>(); 
} 

Một cách để gọi nó là như vậy:

List<Integer> myList = createEmptyList(); // Compiles 

Tại sao tôi không thể gọi nó bằng cách đi qua một cách rõ ràng đối số kiểu chung chung? :

Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why? 

Tôi gặp lỗi Illegal start of expression từ trình biên dịch.

+1

Cheekysoft giải thích tại sao, nhưng nếu bạn thực sự cảm thấy cần phải thêm các loại def thứ hai, chỉ cần thêm tên lớp trước khi gọi hàm tĩnh: Danh sách myList = MyClass. createEmptyList(); –

Trả lời

28

Khi trình biên dịch java không thể suy ra kiểu tham số của chính nó cho một phương thức tĩnh, bạn luôn có thể truyền nó bằng cách sử dụng tên phương thức đầy đủ: Class. < Type> method();

Object list = Collections.<String> emptyList(); 
+6

Đối với phương pháp không tĩnh, bạn có thể sử dụng từ khóa này: ' Danh sách đối tượng = this. emptyList(); ' – Roland

1

Đó là khá nhiều thời gian kể từ khi tôi đào vào những phần của Java, nhưng ...

Tại sao bạn không thể làm điều đó có lẽ là một sự lựa chọn thiết kế bởi các nhà phát triển ngôn ngữ. Tuy nhiên, do type erasure được Java sử dụng, thông tin về generics sẽ bị mất vào thời gian biên dịch, vì vậy trong ví dụ của bạn, nó sẽ tạo chính xác cùng một mã byte cho dù bạn có tham số kiểu hay không.

22

Bạn có thể, nếu bạn chuyển loại dưới dạng tham số phương thức.

static <T> List<T> createEmptyList(Class<T> type) { 
    return new ArrayList<T>(); 
} 

@Test 
public void createStringList() { 
    List<String> stringList = createEmptyList(String.class); 
} 

Phương pháp không thể genericised trong cùng một cách mà một loại có thể, vì vậy lựa chọn duy nhất cho một phương pháp với một kiểu trả về generic động, đánh máy - phew đó là một :-) mouthful - là để vượt qua trong loại như một đối số.

Để có Câu hỏi thường gặp thực sự tuyệt vời về Generics Java, see Angelika Langer's generics FAQ.

.
.

Follow-up:

Nó sẽ không có ý nghĩa trong bối cảnh này để sử dụng đối số mảng như trong Collection.toArray(T[]). Lý do duy nhất một mảng được sử dụng có bởi vì cùng một mảng (được phân bổ trước) được sử dụng để chứa các kết quả (nếu mảng đủ lớn để phù hợp với tất cả chúng). Điều này tiết kiệm trên phân bổ một mảng mới tại thời gian chạy tất cả các thời gian.

Tuy nhiên, với mục đích giáo dục, nếu bạn đã muốn sử dụng gõ mảng, cú pháp là rất giống nhau:

static <T> List<T> createEmptyList(T[] array) { 
    return new ArrayList<T>(); 
} 

@Test 
public void testThing() { 
    List<Integer> integerList = createEmptyList(new Integer[ 1 ]); 
} 
+1

-1 Đây là một quan niệm sai lầm phổ biến rằng một lớp học chữ cần phải được chuyển vào một phương pháp chung chung khi không có đối số khác cho phép trình biên dịch suy ra loại chung. Tất cả những gì thực sự cần thiết là cú pháp được đề cập trong câu trả lời của [Xavier] (http://stackoverflow.com/a/25877). Dù sao, như [câu trả lời của Henrik] (http://stackoverflow.com/a/24996) đề cập, không có trường hợp sử dụng thực để chỉ định các tham số kiểu của một đối tượng generic mới khi nó được gán ngay cho một biến - chỉ có kiểu biến đó quan trọng từ đó, ngay cả ở thời gian biên dịch. Đó là lý do đằng sau cú pháp '<>' của Java 7. –

+0

Bạn không sử dụng tham số 'type', vì vậy không nên vượt qua nó – newacct

0

@pauldoo Vâng, bạn là hoàn toàn đúng. Nó là một trong những điểm yếu với java Generics Generics.

Tôi phản hồi với Cheekysoft Tôi muốn đề xuất cũng xem xét cách nó được thực hiện bởi chính người Java, chẳng hạn như T [] AbstractCollection#toArray (T [] a). Tôi nghĩ rằng phiên bản Cheekysofts là tốt hơn, nhưng Java có lợi thế của sự quen thuộc.

Chỉnh sửa: Đã thêm liên kết. Re-edit: Tìm thấy một lỗi trên SO :)


Follow-up trên Cheekysoft: Vâng, vì nó là danh sách một số loại mà nên được trả lại ví dụ tương ứng nên giống như thế:

static <T> List<T> createEmptyList(List<T> a) { 
    return new ArrayList<T>(); 
} 

Nhưng có, chuyển đối tượng lớp học rõ ràng là tốt hơn. Lập luận duy nhất của tôi là của sự quen thuộc, và trong trường hợp chính xác này nó không có giá trị nhiều (trên thực tế nó là xấu).

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