Ошибка приведения Java при попытке создать универсальный массив пользовательских классов - PullRequest
0 голосов
/ 26 декабря 2008

Вот что я пытаюсь сделать:

import java.lang.reflect.*;

class exampleOuter <T extends Number>
{
    private exampleInner<T>[] elements;

    public exampleOuter(Class<T> type, int size)
    {
        elements = (exampleInner<T>[]) Array.newInstance(type, size);
    }
}

Мне сказали, что если я хочу создать универсальные массивы типа T, я должен использовать

elements = (T[]) Array.newInstance(type,size);

Поэтому я попытался расширить это до своего пользовательского класса и получил ClassCastException (Ljava.lang.Double; не может быть приведен к L mypackagename .exampleInner; я объявляю класс в main следующим образом:

exampleOuter<Double> test = new exampleOuter(Double.class,15);

Я могу очень хорошо объявить внутренний класс, а также я могу объявить массивы, которые не являются общими для innerClass, поэтому я представляю, что это что-то в конструкторе externalClass. Есть идеи?

EDIT: Я понимаю, в чем проблема. Когда я создаю новый экземпляр массива, я создаю массив значений типа double, а не exampleInner. Я думаю. Если это так, мне нужно найти способ создать массив exampleInner, передав в функцию только Double.class.

РЕДАКТИРОВАТЬ 2: Я понимаю, что универсальные массивы не безопасны для типов, но я все равно должен их использовать, потому что мой учитель требует, чтобы мы их использовали.

РЕДАКТИРОВАТЬ 3: Мне сказали, что для использования универсальных массивов я должен был распределить их таким образом, и для этого мне нужны размышления, я думаю. Компилятор говорит мне, что класс использует небезопасные или непроверенные операции, но я должен использовать универсальные массивы, и я знаю, как это сделать. Если есть лучший способ, я поменяю код.

Ответы [ 4 ]

1 голос
/ 26 декабря 2008

Вот решение, которое я придумала:

public exampleOuter(Class<T> type, int size)
{
    innerClass<T> aux = new innerClass<T>(); 
    elements = (exampleInner<T>[]) Array.newInstance(aux.getClass(), size);
}

Я думал, что это также будет работать:

elements = (exampleInner<T>[]) Array.newInstance(innerClass<T>.class, size);

Но это не так, вероятно, из-за того, как дженерики реализованы в Java (стирание типов и все такое).

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

РЕДАКТИРОВАТЬ: Второй подход не работал, потому что я использовал innerClass<T>.class вместо innerClass.class. Спасибо за предложение, я буду использовать его сейчас.

0 голосов
/ 02 мая 2009

У вас нет «создания универсального массива» здесь. Тип компонента массива - "exampleInner" (ну, это должен быть exampleInner, но типы компонентов массива должны быть "reified типами", поэтому он не может хранить во время выполнения.), Который известен во время компиляции. Поэтому вам не нужно передавать параметр Double.class.

Что вам действительно нужно сделать, так это создать массив параметризованного типа. Одним из способов сделать это является создание массива необработанного типа и приведение его к массиву параметризованного типа. Это позволит вам использовать массив, как вы это обычно делаете, и получит преимущества, связанные с отсутствием приведения типов к вещам и прочим.

Технически, это неконтролируемое приведение, потому что теоретически оно может вызвать неожиданные проблемы позже, потому что не может помешать вам поместить неправильный тип объектов в массив. Но так как это частная переменная в вашем классе, и я предполагаю, что вы манипулируете ею только внутри своего класса, и если вы доверяете своему собственному коду для его правильного использования, тогда он будет работать.

import java.lang.reflect.*;

class exampleOuter <T extends Number>
{
    private exampleInner<T>[] elements;

    @SuppressWarnings("unchecked")
    public exampleOuter(int size)
    {
        elements = (exampleInner<T>[]) new exampleInner[size];
    }
}
0 голосов
/ 26 декабря 2008

T расширяет Number, и вы пытаетесь привести его к exampleInner, который, я сомневаюсь, находится в нужном месте в иерархии Number.

Попробуйте без вашего примера Inner. Или попробуйте передать exampleInner в качестве аргумента типа конструктору exampleOuter.

0 голосов
/ 26 декабря 2008

Вы создаете для некоторого конкретного T объект типа T[] и присваиваете его полю типа exampleInner<T>[], что будет ошибкой.

Для T extends Number: тип стирания T[] равен Number[]; для стертого типа exampleInner<T>[] есть exampleInner[]. Но предупреждения компилятора должны были указывать, что вы все равно что-то делаете не так.

Но вы почти наверняка не нуждаетесь в отражении, поэтому не используйте его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...