Тип шаблона, если шаблон является возвращаемым значением (Java).

StackOverflow https://stackoverflow.com/questions/1721109

Вопрос

Мне было интересно, каков тип данных переменной шаблона, если возврат установлен в шаблон.Я где-то видел это в коде, но не знаю, куда оно приводит значение, полученное из сеанса.

public class RequestObject {
    public <T> T getFromSessionMap(String sessionKey) {
        return (T)session.getAttribute(sessionKey);
    }
}

Код для этого снаружи:

MyClassType type = request.getFromSessionMap("abc");

В строке возникает ClassCastException при приведении к моему объекту.Но когда я добавляю для просмотра session.getAttribute("abc"), он показывает, что тип — MyClassType.Любая помощь будет оценена по достоинству.

Очевидно, этот специальный код для использования шаблона делает возврат getFromSessionMap переменным типом и, следовательно, нет необходимости в приведении.Это работает во всех случаях, но внезапно в одной части кода произошел сбой.

Это было полезно?

Решение

По -видимому, этот специальный код для использования шаблона делает возврат GetFromSessionMap типа переменной и, следовательно, нет необходимости в актере.

Принципиально там должно быть приведение типа где-то между получением результата session.getAttribute(sessionKey) и задание на MyClassType.Язык Java (и JVM) не позволит какой-то объект, который не является MyClassType экземпляр (или его подтип), который будет присвоен MyClassType переменная.

Независимо от того, как вы пишете код, должно произойти приведение типа.А поскольку атрибут (по-видимому) не является MyClassType (или подтип), вы получаете ClassCastException.

Итак, реальный вопрос: почему вы не получаете ошибку компиляции?И ответ @SuppressWarnings("unchecked")!Если вы удалите это предупреждение, вы получите сообщение об ошибке «небезопасное преобразование типов» для этой строки:

return (T) session.getAttribute(sessionKey);

По правде говоря, Java не может выполнить (реальное) приведение типа к универсальному типу.И именно на это указывает предупреждение/сообщение об ошибке.Фактически, как только код будет скомпилирован, этот код

public <T> T getFromSessionMap(String sessionKey) {
    return (T)session.getAttribute(sessionKey);
}

на самом деле ничем не отличается по смыслу от этого:

public Object getFromSessionMap(String sessionKey) {
    return session.getAttribute(sessionKey);
}

Технически это называется «стиранием типа».

Так где же на самом деле происходит проверка/приведение типов?Ответ находится в этой строке:

MyClassType type = request.getFromSessionMap("abc");

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

Другие авторы предлагали добавить аргумент класса в getFromSessionMap.Само по себе это делает абсолютно ничего.Если вы также замените тело метода на:

return clazz.cast(session.getAttribute(sessionKey));

вы заставите метод фактически выполнить настоящую проверку типа.Но это единственная причина ClassCastException бросить в другое место.И оператор присваивания все равно будет выполнять скрытое приведение типов!!

Другие советы

В примере вопроса тип возвращаемого значения: T.Удаленный тип будет Object как, неявно, T extends Object.Фактическое приведение выполняется в байт-коде вызывающего метода (вы можете использовать javap -c чтобы увидеть это).

Как правило, вам следует сохранять как можно меньшее количество объектов «верхнего уровня» в сеансах.Одним из преимуществ этого является то, что больше нет необходимости в подобных хакерских методах.

Буду признателен за любую помощь, поскольку мой код сталкивается с ClassCastException.

Если вы получаете ClassCastException, это означает, что вы пытаетесь преобразовать что-то в то, чем оно не является, как в следующем коде:

Map session = new HashMap();
session.put("date", "2009-11-12");
Date today = (Date) session.get("date"); // tries to convert String to Date

А ClassCastException должно иметь подробное сообщение, например «java.lang.String не может быть преобразовано в java.util.Date».

Вы используете приведение типов внутри тела метода ('(T)session.getAttribute(sessionKey)').

Это означает, что вы явно говорите компилятору «Я абсолютно уверен, что возвращенный объект IS-AT T, и готов обработать ошибку, если это не так».

Здесь ваше предположение о типе атрибута было неверным, и вы получили ошибку.Итак, все правильно, и среда выполнения уже предоставляет вам реальный тип объекта атрибута, который не является ЭТО МойКлассТип.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top