2012-05-20 25 views
5

Tôi đang cố gắng triển khai bộ sưu tập được liên kết bằng cách sử dụng Generics, giống như sau.Lỗi biên dịch tạo mảng chung từ lớp bên trong

public class A<E> { 

    private class B { 

    private B[] b; 
    private E item; 

    private B() { 
     this.b = new B[2]; 
    } 

    } // end inner class B 

} // end class A 

A là bộ sưu tập và B là phần tử hoặc nút trong bộ sưu tập có tham chiếu mảng kế thừa/tiền nhiệm và một mục.

Tạo mảng không được phép. Lỗi tôi nhận được là generic array creation. Tôi có đúng khi nghĩ rằng những gì nó thực sự tạo ra là một mảng của A<E>.B?

Nếu không, điều gì gây ra lỗi?

Nếu có, làm thế nào tôi có thể giải quyết vấn đề này?

Tôi rõ ràng đã bỏ qua một số lượng đáng kể mã, nếu những gì tôi đã cung cấp là không đủ vui lòng cho tôi biết. Lời khuyên nào sẽ được đánh giá cao. Cảm ơn bạn.

CHỈNH SỬA 1: Tôi đã đề cập rằng loại tham số phải giống nhau trong A như trong B. Vì vậy, việc chuyển <E> đến lớp bên trong là không thể, vì nó tạo ra E#2 và để lại A với E#1.

+0

Không cụ thể một câu trả lời cho câu hỏi của bạn, nhưng nó sẽ là thiết kế tốt hơn để có hai biến ' người tiền nhiệm 'và' người kế thừa 'của loại B thay vì một mảng gồm hai phần tử. Làm cho lớp của bạn dễ đọc hơn. Tôi đoán nó cũng sẽ làm cho vấn đề của bạn biến mất? –

+0

WRT Edit1, hãy thử một 'static class B ' và bạn sẽ không có vấn đề đặt tên. Mảng vẫn sẽ không hoạt động, vì nó là Chung. –

+0

Bạn cũng có thể giải quyết vấn đề này bằng cách sử dụng bộ sưu tập chung thay vì một mảng. – trutheality

Trả lời

4

Bạn gọi B thừa hưởng chung từ lớp bên ngoài, vì nó không phải là tĩnh. Và bạn không thể chỉ làm cho nó tĩnh, bởi vì nó sẽ cần E nữa.

Vì vậy, mảng B.b của bạn thực sự sẽ cần một kiểu đó là chung chung, ví dụ: A<E>.B hoặc nếu bạn muốn thay đổi mã của bạn để một lớp bên trong tĩnh, A.B<E> (nếu bạn sẽ sử dụng private static class B<E>).

Trong Java, do cách generics được thực hiện (bằng cách xóa), loại mảng không được xác định rõ. Một mặt, nó phải là một mảng của B, mặt khác, nó phải là một mảng của Object.

Giải pháp khả thi nhất có vẻ là sử dụng Object[] và truyền một cách rõ ràng. Nếu bạn muốn tăng độ an toàn kiểu, bạn có thể sử dụng một số ArrayList<B>, sử dụng nội bộ Object[]!

Trong mã cụ thể, B b1, b2; cũng có thể là tùy chọn thực sự nhanh hơn (không kiểm tra giới hạn) và cần ít bộ nhớ hơn (không có đối tượng mảng; không có thông tin kích thước).

+0

Tôi đã nghĩ đến việc sử dụng các tham chiếu b1, b2 riêng biệt. Có vẻ đây là cách phù hợp nhất để đi. Nó chỉ làm cho việc truyền tải phức tạp hơn của bộ sưu tập trong một số phương thức. Cảm ơn bạn đã phản hồi, rất hữu ích. – comfortablejohn

-2

Bạn cần phải vượt qua E để các lớp bên trong cũng

private class B<E> { 

      private B[] b; 
      private E item; 

      private B() { 
       this.b = new B[2]; 
      } 

     } // end inner class B 
+2

Sẽ không cung cấp cho cùng một lỗi? –

+0

Có. Và theo chỉnh sửa của tôi, tôi yêu cầu các kiểu giống nhau ở cả lớp bên ngoài và bên trong. Việc làm ở trên sẽ có nghĩa rằng mặc dù cả hai có thể được chuyển thành cùng một loại, nói 'A 'làm cho chúng cả hai số nguyên, chúng không thể so sánh hoặc tương thích khi tham chiếu giữa hai. – comfortablejohn

+0

Xin lỗi, tôi không thấy bất kỳ lợi ích nào. Trong thiết lập của bạn, nó nên IMHO thực sự là 'private static class B ' để không nhận được một quá tải tên, và nó sẽ vẫn không cho phép tạo mới 'mảng B [2]'. –

2

B là lớp bên trong không tĩnh. Điều đó có nghĩa là nó có một tham chiếu đến một thể hiện của lớp kèm theo. Vì vậy, nó được ngầm hóa tham số bởi tham số kiểu của lớp ngoài. Vì vậy, khi bạn viết B, điều đó có nghĩa là A<E>.B. Để tạo một mảng, bạn nên sử dụng lớp thô.Tuy nhiên, B không phải là lớp thô; để tham khảo các lớp liệu bạn cần phải hội đủ điều kiện một cách rõ ràng: A.B

Vì vậy, đây là bạn muốn:

this.b = new A.B[2]; 
Các vấn đề liên quan