2016-10-06 11 views
12

Khi tôi khởi tạo List, tôi có thể làm điều này:rắc rối khởi Danh sách <Object[]> Sử dụng Arrays.asList

List<Object[]> foo = new ArrayList<>(); 
foo.add(new Object[]{816, "foo", 2.6}); 

Nhưng khi tôi muốn đơn giản hóa nó bằng cách sử Arrays.asList:

List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}); 

Nó không thể biên dịch có lỗi:

incompatible types: inference variable T has incompatible bounds 
equality constraints: java.lang.Object[] 
lower bounds: java.lang.Object 

Tại sao nó không thể thực hiện đúng suy luận kiểu và cách sửa lỗi này?

+0

https://stackoverflow.com/questions/1248763/arrays-aslist-of-an-array –

+2

Là nguyên tắc chung chung, không bao giờ trộn chung và mảng. (Bạn được phép bỏ qua quy tắc này một khi bạn hiểu tại sao đó là nguyên tắc tốt ngay từ đầu.) –

Trả lời

12

Hãy nhớ rằng ... chỉ là cú pháp đường cho một tham số mảng.Bạn có thể gọi một phương thức với một tham số variadic foo(Object...) hoặc sử dụng

foo("hello", 1); 

hoặc

foo(new Object[]{"hello", 1}); 

kể từ khi biên dịch xây dựng hình thức thứ hai anyway.

Vì loại bộ thu không được xem xét khi trình biên dịch nhập loại, nó xem Arrays.asList(new Object[]{"bar", 286}) và nghĩ rằng bạn muốn tạo danh sách Object, không phải danh sách singleton Object[].

Cách đơn giản nhất với cú pháp hiện tại của bạn là chỉ để thêm một tham số kiểu tường minh:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286}); 

Thêm <Object[]> nói với trình biên dịch những gì T nên.

13

Khi bạn chuyển một loạt loại tham chiếu đến Arrays.asList, bạn nhận được List của loại tham chiếu đó.

Do đó Arrays.asList(new Object[]{"bar", 286}) trả về một số List<Object>, không phải là List<Object[]>.

7

Nếu danh sách của bạn chỉ có một phần tử trong đó, Collections.singletonList(new Object[] {...}) là một lựa chọn tốt hơn, vì nó tránh biến dạng và làm cho hành vi rõ ràng hơn tại trang web cuộc gọi.

2

Arrays#asList chữ ký:

public static <T> List<T> asList(T... a) 

Các kiểu trả về là List<T>. Bây giờ bạn nên tự hỏi mình là gì T?

TObject, vì vậy loại trả về sẽ là List<Object> và không phải List<Object[]>.

1

Cuộc gọi của bạn:

Arrays.asList(new Object[]{"bar", 286}); 

tạo ra một danh sách ra khỏi Object[]. Vì vậy, dữ liệu được chuyển đổi thành List<Object> mới.

Vì vậy, Arrays.asList(new Object[]{"bar", 286}).get(0); sẽ trả lại "thanh".

Trong cuộc gọi này:

List<Object[]> foo = new ArrayList<>(); 
foo.add(new Object[]{816, "foo", 2.6}); 

bạn đang tạo một List<Object[]> (2Dimensional) và thêm một yếu tố sau nó: foo.add(..);. Vì vậy, bạn đang thêm một phần tử bao gồm Object[]. nếu bây giờ bạn gọi foo.get(0); bạn sẽ nhận được một Object[] bao gồm: 816, "foo", 2,6

Tôi nghĩ rằng bạn muốn làm:

Object[] oa = new Object[]{""}; 
Object[] ob = new Object[]{""}; 
List<Object[]> list = Arrays.asList(oa, ob); 

Nếu bạn có thắc mắc, đừng ngần ngại hỏi tôi :)

1

Khi bạn sử dụng List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}); bạn thực sự có một chiều mảng hai và bạn CAND giải quyết vấn đề đó bằng cách làm List<Object[]> bar = Arrays.asList(new Object[][]{new Object[]{"bar","asd",123}});

4

Vấn đề là Arrays.asList là phương pháp varargs mà về mặt kỹ thuật nhận được một mảng chứa đối số và do khả năng tương thích với mã pre-generics vẫn chấp nhận một mảng thay vì danh sách đối số. Khi truyền một mảng duy nhất, cuộc gọi không rõ ràng và sẽ được xử lý như lời gọi phương thức trước varargs.

Vấn đề sẽ biến mất khi bạn có nhiều hơn một đối số:

List<Object[]> bar = Arrays.asList(new Object[]{"bar", 286}, new Object[]{"baz", 123}); 

Nếu bạn chỉ có một đối số bạn có thể hỗ trợ các trình biên dịch bằng cách chèn một kiểu tường minh yếu tố danh sách:

List<Object[]> bar = Arrays.<Object[]>asList(new Object[]{"bar", 286}); 

Ngoài ra, bạn có thể sử dụng

List<Object[]> bar = Collections.singletonList(new Object[]{"bar", 286}); 

để tạo danh sách có kích thước không thay đổi. Lưu ý rằng điều này khác với Arrays.asList, vì sau này trả về danh sách kích thước cố định nhưng vẫn có thể thay đổi được qua set.

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