Исключение класса Cast в Java: не может быть приведено

Может ли кто-нибудь сказать мне, в чем ошибка в этом коде?

public class Node<T> {
    private int degree;
    @SuppressWarnings("unchecked")
    T[] keys ;
    Node<T>[] children;
    Node(int degree) {
        System.out.println(degree);
        this.degree = degree;
        @SuppressWarnings("unchecked")
        Node<T>[] children = (Node<T>[])new Object[degree * 2];
        @SuppressWarnings("unchecked")
        T[] keys       = (T[])new Object[(degree * 2) - 1];
     }

     public static void main(String[] s) {
        Node<Integer> a = new Node<Integer>(5);
     }
}

По сути, мне нужна самореферентная вещь, в которой объект хранит массив своих собственных объектов. я получаю эту ошибку

Исключение в потоке "основной" java.lang.ClassCastException: [Ljava.lang.Object; нельзя привести к [Tree.Node;

Дерево — это имя моего пакета.


person Community    schedule 16.02.2011    source источник
comment
Как правило... Если есть ошибка компиляции, вы должны изменить свою философию. Попытка обмануть JVM, вероятно, приведет к сбою. Если бы не сбой, это была бы не ошибка компиляции, а предупреждение.   -  person corsiKa    schedule 16.02.2011
comment
массивы и дженерики не очень хорошо ладят. используйте ArrayList‹T›, если можете.   -  person irreputable    schedule 16.02.2011
comment
Не связано, но вы должны принять к сведению, что вы создаете локальные переменные, называемые дочерними элементами и ключами в своем конструкторе, а не инициализируете свои переменные экземпляра с теми же именами. Вероятно, не то, что вы хотели.   -  person Highland Mark    schedule 17.02.2011


Ответы (4)


Вы не можете создать типизированный массив. Вы должны сделать это:

Node<T>[] children = new Node[degree * 2];

И разобраться с тем, что массивы нетипизированы :(

person corsiKa    schedule 16.02.2011
comment
Однако это дает предупреждение компилятору. - person aioobe; 16.02.2011
comment
Это дает предупреждение. И это должно дать предупреждение, потому что это то, о чем следует беспокоиться. Но есть важное различие между предупреждением и ошибкой. Предупреждения говорят, что компилятор заметил что-то, что может стать проблемой, тогда как ошибки говорят, что компилятор заметил что-то, что является проблемой. - person corsiKa; 16.02.2011
comment
Я выбрал это в качестве своего ответа, потому что то, что я пытаюсь реализовать, не может иметь список, поскольку с самого начала он должен иметь фиксированный размер... Спасибо... - person ; 17.02.2011

Вместо массивов для ваших дочерних элементов и ключей используйте List<Node<T>> и List<T>ArrayList в качестве реализации). Таким образом, вы скроете сложность создания и приведения массива внутри класса ArrayList. (Он также использует Object[], но преобразует только get() и аналогичные методы вместо того, чтобы пытаться получить общий массив).

Или, поскольку похоже, что вы все равно создаете карту, используйте Map<T, Node<T>> для своих ключей и узлов (хотя тогда у вас нет доступа к индексу).

person Paŭlo Ebermann    schedule 16.02.2011

Ты не сможешь это сделать:

Node<T>[] children = (Node<T>[])new Object[degree * 2];

Здесь вы создаете массив объектов, а объект не является узлом. Вместо этого вы должны создать массив узлов, т.е.

Node<T>[] children = new Node[degree * 2];

У вас есть эта же ошибка дважды в вашем коде.

person brent777    schedule 16.02.2011

Вы не можете привести объект к узлу:

Node<T>[] children = (Node<T>[])new Object[degree * 2];

Либо вы думаете об этом неправильно: «Любой объект может быть узлом», когда единственное, что верно, это «Каждый узел является объектом», либо вы привыкли к C++ или аналогичному, в котором вы можете использовать указатель void на любой другой указатель.

Кроме того, у вас не может быть массивов универсальных типов. Например, вам нужно будет создать тип оболочки. StringNode extends Node<String>, чтобы сохранить их в массиве.

Этот фрагмент, например, прекрасно компилируется:

class Node<T> {
}

class StringNode extends Node<String> {
}

public class Test {
    public void method() {
        Node<String>[] children = new StringNode[5];
    }
}
person aioobe    schedule 16.02.2011
comment
Вы не можете создать new Node<T>[] - ошибка компиляции при создании универсального массива. - person corsiKa; 16.02.2011
comment
Вы можете написать (Node<T>[])new Node<?>[] (с непроверенным приведением). - person Paŭlo Ebermann; 16.02.2011