Java Generics: проблема приведения типа (ClassCastException) - PullRequest
2 голосов
/ 16 ноября 2010

У меня проблемы с выяснением, как правильно привести обобщенный объект в Java к типу, расширяющему универсальный объект.

Например, скажем, некоторые настройки, подобные следующим:

public class Parameters extends SomeCustomMap<String, String>
{
   ...
}

public class SomeCustomMap<K, V> implements Map<K, V>
{
    public SomeCustomMap<K, V> getSubSet(...)
    {
        SomeCustomMap<K, V> subset;

        ...

        return subset;
    }
}

class ExampleApp
{
    private void someMethod()
    {
        Parameters params;
        Parameters paramsSubSet;

        try
        {
            ...

            paramsSubSet = (Parameters) params.getSubSet(...);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

Запуск кода, аналогичного приведенному выше, последовательно вызывает исключение ClassCastException, подобное которому я не до конца понимаю. Будем благодарны за любые советы по правильной настройке сценария, аналогичного описанному выше! А именно, как я могу правильно привести объект SomeCustomMap, который возвращается из метода params.getSubSet (...) обратно в объект Parameters?

Заранее спасибо!

Ответы [ 5 ]

2 голосов
/ 16 ноября 2010

Ваша проблема в том, что подмножество, возвращаемое getSubSet, является экземпляром SomeCustomMap, а не Parameters.

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

Я не знаю, как вы создаете экземпляр подмножества, но, возможно, вы могли бы использовать шаблон дизайна шаблона и некоторые дженерики для решения вашей проблемы.

1 голос
/ 16 ноября 2010

Вы можете попробовать что-то вроде этого:

public <T extends SomeCustomMap<K, V>> T getSubSet(...){
    T subset = (T)this.clone();
    subset.clear();

    return subset;
}

создание выглядит немного забавно - смело меняйте его на что угодно:)

В качестве бонуса вам не нужнолитой:)

paramsSubSet = params.getSubSet(...)
1 голос
/ 16 ноября 2010

Дженерики по своей сути не имеют ничего общего с приведением (за исключением того, что из-за характера стирания общие параметры не могут быть проверены во время приведения).

Если вы получаете ClassCastException вв этом случае это означает, что возвращаемый объект действительно не является экземпляром Parameters.Непосредственно перед произнесением, попробуйте позвонить

System.out.println(params.getSubSet(...).getClass());

и посмотреть, каков фактический класс времени выполнения подмножества.Скорее всего, проблема кроется в другом месте, так как вы ожидаете, что подмножество является объектом Parameters, почти наверняка не правильно во время выполнения - это SomeCustomMap или некоторый другой его подкласс.

1 голос
/ 16 ноября 2010

Хотя я прокомментировал запрос дополнительной информации, основываясь на том, что вы уже опубликовали, я думаю, getSubSet создает SomeCustomMap для возврата (с new SomeCustomMap) куда-нибудь.Если вы не переопределите getSubSet в Parameters, то Parameters.getSubset вернет SomeCustomMap (базовый класс), а не Parameters, поэтому ваш тип преобразования к Parameters завершится неудачей.

(Горячий совет, если вы переопределяете getSubSet в классе Parameters, вы можете изменить тип возвращаемого значения на Parameters и избегать приведения типа.)

0 голосов
/ 16 ноября 2010

Как объяснили другие, проблема в том, что фактический объект, который вы строите в getSubSet(), не является экземпляром Parameters.

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

public static <T extends SomeCustomMap<K, V>> getSubSet(T fullSet)
{
    T subset;

    ... (use fullSet instead of this)

    return subset;
}
...