Java: распаковка значений, хранящихся в объекте, в неизвестный тип

Я строю что-то вроде графа потока данных с узлами и соединениями, которые передают данные между ними. Базовым классом в данном случае является ValueTarget<T>, у которого есть предыдущая и следующая цель для передачи данных туда и обратно. Другие классы расширяют этот класс для предоставления источников данных, объединения данных (например, умножения) и т. д.

Теперь я хотел написать источник данных, который получает значение от любого заданного метода. Он принимает экземпляр java.lang.reflect.Method (а также объект и параметры для его вызова) и использует его для установки данных:

@Override
public T getValue() {

    if (valueCalculator != null) {
        try {
            Object result = valueCalculator.invoke(sourceObject);
            T typedResult = (T)(result);
            return typedResult;
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    return super.getValue();
}

Теперь я попробовал это с помощью метода public int getLength() другого объекта. Однако на графике мне нужно сопоставить этот метод с результатом float. Данное приведение типов не генерирует исключение, но при чтении последнего значения ValueTarget<Float> и использовании его результата в качестве параметра float для другого метода происходит сбой программы с сообщением, что "java.lang.Integer не может быть приведен в java.lang.Float".

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

Есть ли способ выполнить общую распаковку, чтобы иметь возможность преобразовывать упакованные значения в соответствующие типы значений?


person Jay    schedule 17.09.2013    source источник


Ответы (2)


Как насчет использования Number.floatValue()?

Object result = valueCalculator.invoke(sourceObject);
Float f = ((Number)result).floatValue();
System.out.println(f);

... или как вы хотите его использовать.

Здесь я предполагаю, что возвращаемый тип является одним из следующих: BigDecimal, BigInteger, Byte, Double, Float, Integer, Long и Short (все они являются подклассами Number).

person Bernhard Barker    schedule 17.09.2013
comment
Если результат не может быть приведен к типу Number, он снова выдаст ошибку приведения типа. - person Vijay; 17.09.2013
comment
@Vijay Если его нельзя привести к типу Number, я не уверен, каким должно быть поведение. Не существует универсального метода, который допускает другие преобразования, поэтому нет универсального решения. - person Bernhard Barker; 17.09.2013
comment
Я не уверен, именно это вы имели в виду, но, просто используя ‹Number› в качестве наименьшего общего знаменателя для передачи чисел через граф вместо использования определенных типов, таких как Float, я мог бы обойти всю проблему. Спасибо. - person Jay; 17.09.2013

Вы можете использовать библиотеку Apache CommonBeanUtils для преобразования типов во время выполнения.

org.apache.commons.beanutils.ConvertUtils.convert(Object value, Class targetType)

поэтому вы меняете код typecaste

  T typedResult = (T)(result);

заменить на это

 T typedResult = (T)org.apache.commons.beanutils.ConvertUtils.convert(result, T.getClass());
person Vijay    schedule 17.09.2013
comment
К сожалению, ошибка по-прежнему остается: программа по-прежнему аварийно завершает работу с java.lang.Integer, который не может быть приведен к java.lang.Float при использовании (предполагаемого) результата Float где-то еще. - person Jay; 17.09.2013
comment
Попробуйте ключевое слово instanceof. - person Mohammad Ali Asgar; 30.12.2014