2015-08-06 11 views
5

Bất cứ ai có thể giải thích tại sao đoạn mã sau đây biên dịch?Bối rối bởi các generics trong Java

List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three")); 

Có phải do loại tẩy xoá không?

Nếu tôi có các phương pháp sau đây:

public <T> T readProperty(String propName, Class<T> type); 

Làm thế nào tôi có thể chắc chắn rằng nó sẽ trở lại, nói một List<Long> và không phải là một List<String>? Rõ ràng, ở kiểu gọi phương thức tôi chỉ có thể cung cấp List.class và cầu nguyện.

//run and pray 
List<Long> longNums = readProperty("prop", List.class); 

Nó đã xảy ra với tôi rằng một phương pháp như vậy không đúng chỉ định một danh sách các đối tượng String để một danh sách các số dài, và nó không phải là cho đến khi tôi chạy nó, mà tôi thấy ClassCastException.

+6

Đơn giản chỉ cần - không pha trộn Generics với RAWS. –

+0

Tại sao bạn muốn lưu trữ chuỗi ký tự trong danh sách 'Long'? –

+0

không phải là một chuỗi ký tự, mà là một danh sách các chuỗi. Có lẽ tôi nên diễn giải – preslavrachev

Trả lời

1

Bạn bỏ lỡ kim cương <> (điều này sẽ không biên dịch):

List<Long> longNums = new ArrayList<>(Arrays.asList("one", "two","three")); 
+1

và điều này thậm chí không biên dịch :) –

+0

@ kocko đó là sự thật. Nhưng ít nhất điều này sẽ ngăn chặn lỗi thời gian chạy :) – Maroun

+0

Các bạn có thể giúp tôi giải quyết phần thứ hai không? – preslavrachev

9

Bạn không nên mong đợi chương trình để hành xử một cách chính xác, bởi vì bạn không sử dụng Generics một cách chính xác.

Trước tiên, bạn không nên trộn Generics với RAWS, có nghĩa là tuyên bố này

List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three")); 

không hợp lệ (về tính đúng đắn). Nếu đó là:

List<Long> longNums = new ArrayList<Long>(Arrays.asList("one", "two", "three")); 

nó thậm chí sẽ không biên dịch và bạn sẽ gặp lỗi lúc biên dịch (không phải lúc chạy, có thể khó hiểu và đáng sợ hơn).

Vì vậy, để có được biên dịch, danh sách của bạn nên được định nghĩa là:

List<String> longNums = new ArrayList<>(Arrays.asList("one", "two", "three")); 

Hơn nữa, liên quan đến tuyên bố này

//run and pray 
List<Long> longNums = readProperty("prop", List.class); 

có thực sự không có cách nào để đảm bảo rằng readProperty sẽ trả về List<Long>, vì vậy bạn sẽ phải thực hiện một dàn diễn viên hoặc thêm chú thích @SuppressWarnings. Lý do cho việc này là tính năng xóa của trình biên dịch - loại tham số Long bị xóa và biến mất trong Thời gian chạy (khi thực tế readProperty() được thực thi và giá trị của prob thu được qua Phản ánh).

+0

Vâng, tôi biết. Phần đầu tiên là một ví dụ minh họa cho phần thứ hai. Cách để giải quyết điều đó là gì? – preslavrachev

+0

@ user1107412, tôi đã cập nhật câu trả lời. –

+0

Cảm ơn. Tôi ước có thực sự là một cách mà tôi có thể chỉ định trong các thông số mà tôi thực sự, thực sự mong đợi một Danh sách . Một cái gì đó như (nếu nó tồn tại) Danh sách .class. Vấn đề lớn của tôi là nhiệm vụ được giao mà không có vấn đề gì trong thời gian chạy, và tôi chỉ tìm ra vấn đề, khi tôi cố truy cập một phần tử của danh sách. Tôi đã thử đúc một cách rõ ràng để (Danh sách ) nhưng điều đó dường như không giúp được gì. – preslavrachev

1

Đây là hai câu hỏi riêng biệt thực sự.

List<Long> longNums = new ArrayList(Arrays.asList("one", "two", "three")); 

Vì lý do tương thích nguồn, raw type được cho phép trong những trường hợp này. Bạn không nên dựa vào điều này bởi vì như bạn có thể thấy, nó đánh bại toàn bộ ý tưởng về generics.

Đối với câu hỏi thứ hai, bạn có thể để bên ngoài vấn đề này bằng cách làm một cái gì đó như thế này:

public <T> List<T> readListProperty(String propName, Class<T> type); 
... 
List<Long> longNums = readProperty("prop", Long.class); 

Đó là nhiều hơn một workaround hơn một giải pháp và không phải lúc nào cũng áp dụng.(Ví dụ: khi bạn cần các loại trả lại phức tạp hơn, chẳng hạn như Map<String,List<String>>)

+0

Rất tiếc, tôi không thể chạm vào chữ ký phương thức. Ngoài ra, tôi đã cố gắng đúc rõ ràng kết quả vào Danh sách nhưng điều đó cũng không giúp được gì. Nhiệm vụ vẫn tiếp diễn mà không có vấn đề gì. Tôi chỉ tìm hiểu về vấn đề đúc, khi tôi cố gắng truy cập vào một phần tử của danh sách. – preslavrachev

+0

Thật không may là làm thế nào nó là nếu bạn không thể thay đổi phương pháp, không có lừa biên dịch thời gian để giúp bạn có được xung quanh. Bạn có thể kiểm tra kết quả theo cách thủ công khi chạy, nhưng việc kiểm tra một phần tử không đủ, bạn cần phải kiểm tra tất cả chúng vì có thể danh sách của bạn sẽ chứa 6 'Long', theo sau là một 'Chuỗi'. – biziclop

0

Nếu bạn xác định Danh sách là ArrayList, java không biết loại đối tượng nằm trong đó. Bạn có thể gán nó cho một số ArrayList<Long>, nhưng bạn sẽ gặp lỗi khi bạn gọi các phương thức hoặc thuộc tính trên các mục, vì loại không khớp.

0

Generic lớp:

public abstract class GenericClass<T> { 

private T managedClass; 
public List<T> readListProp(String propName,T object){ 
    //do stuff using T type instead of Long,String,Double,etc 
} 
Other classes: 
public class FirstClass extends GenericClass<String> 
{... 
//you have a class where T from generic is replaced with String 
} 
public class SecClass extends GenericClass<Double> 
{... 
//you have a class where T from generic is replaced with Double 
} 
+0

Câu trả lời này có vẻ như không liên quan gì đến câu hỏi. Nếu có, vui lòng giải thích! – anderas

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