Не удается привести java.lang.Float к плавающей точке при использовании Class.cast? - PullRequest
1 голос
/ 23 сентября 2011

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

Видите ли, elem.get возвращает Object, который будет Float в случае х и у.

Этот код вызывает исключение, описанное в заголовке:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);
        arg.add(types[i].cast(elem.get(names[i])));
    }
}

Код используется для определения списка параметров для создания объекта. И параметры, и имя класса объекта определены во внешнем файле данных (но это не важно).

Решение, то, что мне не нравится (потому что оно теряет гибкость, которую я пытался достичь), имеет в пределах:

if(types[i] == float.class)
{
    float v = (Float)elem.get(names[i]);
    arg.add(v);
} else
{
    arg.add(types[i].cast(elem.get(names[i])));
    break;
}

Другим вариантом будет изменение float.class на Float.class в types, но я не буду этого делать, потому что этот код используется для создания экземпляров объектов, которые имеют float параметры в своих конструкторах.

Спасибо!

1 Ответ

2 голосов
/ 23 сентября 2011

Поскольку тип args является ArrayList<Object>, вы все равно не избегаете бокса:

// This code...
float v = (Float)elem.get(names[i]);
arg.add(v);

// Will actually be equivalent to:
float v = (Float)elem.get(names[i]);
Float boxed = v;
arg.add(boxed);

Если цель заключается в том, чтобы вызвать конструктор с помощью отражения, то вы собираетесь иметь для передачи Float для любых float параметров - вот как это работает.

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

Возможно, вам нужна карта от примитивных типов к типам-обёрткам, например:

private static final Map<Class<?>>, Class<?>> PRIMITIVE_TYPE_MAP =
    buildPrimitiveTypeMap();

private static Map<Class<?>>, Class<?>> buildPrimitiveTypeMap()
{
    Map<Class<?>>, Class<?>> map = new HashMap<Class<?>>, Class<?>>();
    map.put(float.class, Float.class);
    map.put(double.class, Double.class);
    // etc
    return map;
}

Тогда:

String names[] = { "x", "y", "src" };
Class types[] = { float.class, float.class, String.class };

for (int i = 0; i < names.length; i++)
{
    if (elem.containsKey(names[i]))
    {
        par.add(types[i]);

        // For primitive types, only box to the wrapper type
        Class<?> castType = PRIMITIVE_TYPE_MAP.get(types[i]);
        if (castType == null)
        {
            castType = types[i];
        }
        arg.add(castType.cast(elem.get(names[i])));
    }
}

На самом деле, если вы уверены, что значения уже имеют правильный тип, я подозреваю, что вы можете просто сделать:

arg.add(elem.get(names[i]));

В конце концов, вы просто приводите к определенному типу, а затем снова теряете информацию о типе ... с помощью вызова cast выполняется проверка правильности типов времени выполнения, поэтому вы можете захотеть сохраните это по этой причине.

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