2015-02-12 27 views
5

Tôi có một mã mẫu để thử. Mã này dường như không có lỗi biên dịch. Tại sao nó sử dụng nút lớp lồng nhau tĩnh? khi tôi xóa static trong Node lớp lồng nhau và biên dịch, lỗi hiển thị create generic array trong private Node[] next = new Node[R];. Chuyện gì xảy ra với Trái Đất?Tại sao lớp lồng nhau tĩnh?

public class TrieST<Value> { 
    private static final int R = 256;  // extended ASCII 


    private Node root;  // root of trie 
    private int N;   // number of keys in trie 

    // R-way trie node 
    private static class Node { 
     private Object val; 
     private Node[] next = new Node[R]; 
    } 


    public TrieST() { 
    } 
} 
+4

Trước tiên, bạn có biết tại sao mảng chung không được phép không? (ví dụ 'new ArrayList [5];' hiển thị lỗi này) – immibis

+0

có thể trùng lặp của [Làm thế nào để tạo một mảng chung?] (http://stackoverflow.com/questions/18581002/how-to-create-a-generic -array) – alfasin

+0

Bạn có thể giải thích tại sao không có lỗi như vậy khi thêm tĩnh? – Peterxwl

Trả lời

2

Giả sử rằng trong mã của bạn Đoạn bạn đang sử dụng một lớp bên trong không tĩnh thay vì một lớp lồng nhau tĩnh như thế này: private class Node, trong trường hợp đó, bạn sẽ phải cố gắng để nhanh chóng một Array đó là không thể, chúng ta không thể nhanh chóng một Array trong một lớp học chung, vì Generics không có bất kỳ thông tin liên quan đến loại của họ khi chạy, trong khi biểu hiện các mảng tạo định các loại nguyên tố.

Vì vậy, lý do tại sao sử dụng một Static Nested Class biên soạn, đó là các lớp học như vậy được coi như là một lớp "cấp cao nhất" (về hành vi):

Một lớp lồng nhau tĩnh tương tác với các thành viên dụ của lớp ngoài của nó (và các lớp khác) giống như bất kỳ lớp cấp cao nhất nào khác. Trong hiệu ứng , một lớp lồng nhau tĩnh là hành vi một lớp cấp cao nhất mà đã được lồng trong một lớp cấp cao nhất để tiện lợi đóng gói.

Bây giờ, chúng ta hãy xem tất cả những điều này vào xem xét, và trở lại các lỗi chính xác hiển thị bởi trình biên dịch:

Không thể tạo một mảng chung của TrieST<Value>.Node

Điều đó có nghĩa rằng loại của array bạn muốn tạo là TrieST<Value>.Node có loại thời gian chạy không được biết, do đó các loại khác nhau có thể được chèn vào mảng next. rõ ràng hơn và cũng ví dụ giải thích có thể được tìm thấy trong Cannot Create Arrays of Parameterized Types

Trong khi đó, một lớp lồng nhau tĩnh được không hành xử như một lớp bên trong của TrieST<Value>, do đó instiating một mảng bên Node sẽ không là bất hợp pháp vì nó không phải của các loại TrieST<Value>.Node , thuộc loại Node (như nếu đó là lớp cấp cao nhất).

+0

Bạn có thể giải thích thêm lý do tại sao và làm thế nào lass tĩnh lồng nhau "ngăn chặn" lỗi này coi là lớp cấp cao nhất? – Peterxwl

+0

một lớp cấp cao nhất là một lớp không bên trong, do đó có nghĩa là không có mối quan hệ tiềm ẩn giữa lớp lồng nhau tĩnh và lớp bên ngoài, do đó việc tạo một mảng không ảnh hưởng đến lớp bên ngoài (lớp chung của bạn) – Tarik

+0

@Peterxwl Tôi chỉ cần thêm một bản cập nhật, xin hãy xem – Tarik

1

Vì với tĩnh bạn tạo: Node[] next = new Node[R] và với lớp bên trong không tĩnh, bạn tạo nút được liên kết với một thể hiện của lớp bên ngoài, có kiểu chung. Và việc tạo ra các mảng chung bị cấm.

Nhưng cho phép sao lưu một vài bước: cách nhanh chóng một bên trong lớp (không tĩnh) là như sau (ví dụ):

class TrieST<V> { 
    private static final int R = 256;   

    private Node root;  // root of trie 
    private int N;   // number of keys in trie 
    private TrieST<String> inst = new TrieST<String>(); // must create an instance of the outer class first 

    // R-way trie node 
    private class Node { 
     private Object val; 
     private TrieST<String>.Node next = inst.new Node(); //must use an instance of the outer class to instantiate an object of the inner class 
    } 

    public TrieST() { 
    } 
} 

Bây giờ, nếu chúng tôi sẽ cố gắng thay đổi việc thực hiện trên từ một thể hiện của các lớp bên trong để một mảng, chúng ta sẽ nhận được generic array creation bởi vì nó bị cấm để tạo mảng với kiểu chung chung do hiệp phương sai chất của mảng (Shape[]super của Triangle[]) mà không làm việc tốt với các bất biến bản chất của generics (List<Object>không phải siêu số List<String>). Trong Bloch "Hiệu quả Java" cung cấp giải thích chi tiết hơn nếu bạn muốn đào sâu.

Nếu bạn nhấn mạnh vào việc sử dụng lớp bên trong, bạn có thể giải quyết giới hạn này bằng cách sử dụng Array.newInstance(). vào thời gian chạy như sau:

private Node[] next = (Node[]) Array.newInstance(Node.class, R); 
+0

nếu tôi vẫn muốn một 'Nút [] tiếp theo' trong lớp bên trong không tĩnh? – Peterxwl

+0

@Peterxwl bạn có thể lừa trình biên dịch bằng cách thực hiện: 'private Node [] next = (Node []) Array.newInstance (Node.class, R);' Tôi sẽ thêm nó vào câu trả lời. – alfasin

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