Неспособность принудительно набрать тип в java - PullRequest
1 голос
/ 05 марта 2012

У меня есть полный тупик, и я поделюсь им со всеми, чтобы узнать, знаете ли вы, что происходит.

Это структура данных

Map<String, Object> objectMap

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

Это функция, которую я использую для получения этих значений:

public <T> T get(String variable, T defaultValue) {
    // returns either the object from the map, or the default if its not in the map.
    Object value = getObject(variable, defaultValue); 
    logger.debug("default value is of type " + defaultValue.getClass().getName());

    // Attempt to get around casting issue
    if (value instanceof Number)
    {
        value = (Number) value;
    }
    T ret = (T) value;
    logger.debug("Variable " + variable + " which is of type " + value.getClass().getName() + " and returning as " + ret.getClass().getName() + " (is number: " + (value instanceof Number) + ")");

    return ret;
}

И это код вызова:

public int getFoo() { return this.<Integer>get("foo", 0); }

Это вывод, который я вижу в журналах:

default value is of type java.lang.Integer
Variable foo which is of type java.lang.Long and returning as java.lang.Long (is number: true)

Прямо перед тем, как он потерпит неудачу с:

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer

Что меня больше всего беспокоит, так это то, что тип класса выглядит как Long, несмотря на попытку заставить класс использовать Integer .

Я что-то упускаю или нарушаю какую-то концепцию обобщения Java?

Спасибо за любую помощь

Ответы [ 3 ]

2 голосов
/ 05 марта 2012

Значение, возвращаемое методом getObject, равно java.lang.Long - журнал сообщает вам, что.

Обобщения не являются магическими, они не будут преобразовывать между типами, они просто синтаксический сахар, которыйкомпилятор превращается обратно в броски.Итак, ваш метод:

public <T> T get(String variable, T defaultValue)

действительно:

public Object get(String variable, Object defaultValue)

Когда метод get вызывается с помощью:

this.<Integer>get("foo", 0)

это действительно:

(Integer)this.get("foo", 0)

Следовательно, ClassCastException, поскольку возвращаемое Object является Long, а не Integer.

Не зная точно, чего вы пытаетесь достичь, трудно дать конкретный совет, нокак правило, ваш Map должен использовать общий тип, с которым вы ожидаете иметь дело.В вашем случае это звучит как Integer или Number.Если вам действительно нужно значение int для любого Number (что я сомневаюсь, потому что значение будет усечено, когда оно больше, чем int), вам следует использовать метод Number.intValue().

0 голосов
/ 05 марта 2012

Значение ключа "foo" на вашей карте поддержки, очевидно, имеет тип Long.Вы не можете привести Long к Integer (даже если оба имеют тип Number - и оба имеют тип Object;)

Если вы хотите форсировать Integer, вы должны сделать это при установке значения для "фу "в карту.

0 голосов
/ 05 марта 2012

Это вызвано стиранием типа Java. Типизация Java используется только в исходном коде. Компилятор преобразует код так же, как если бы вы бросили все объекты. Если вы получаете значение Long, это означает, что вы устанавливаете его как значение Long.

Этот код ничего не выполняет:

if (value instanceof Number)
{
    value = (Number) value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...