java.lang.ClassCastException: Z нельзя преобразовать в java.lang.String

Я получаю сообщение об ошибке: java.lang.ClassCastException: Z cannot be cast to java.lang.String при попытке выполнить покрытие (EclEmma) в тесте Junit. Если я запускаю тест регулярно (без покрытия), то он проходит.

Это код (все поля в классе Strings):

@Override
public Map<String, String> getErrors() throws IllegalAccessException, IllegalArgumentException {

    Map<String, String> errors = new HashMap<String, String>();

    for (Field field : this.getClass().getDeclaredFields()) {
        field.setAccessible(true);
        String value = (String) field.get(this);

        if (value.equals("N")) {
            if (!errors.containsKey(field.getName())) {
                errors.put(field.getName(), value);
            }
        }
    }
    return errors;
}

person co.zohar    schedule 18.08.2016    source источник
comment
Код запутан?   -  person Henry    schedule 18.08.2016


Ответы (3)


Проблема в том, что для создания покрытия кода EclEmma добавляет в ваш класс поле private static final transient boolean[] $jacocoData.

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

Лучшее решение — проверить, действительно ли поле, которое вы видите, является полем String, и в противном случае пропустить проверку значения поля:

for (Field field : this.getClass().getDeclaredFields()) {
    field.setAccessible(true);
    if (field.getType() != String.class) {
        continue;
    }
    String value = (String) field.get(this);

    if (value.equals("N")) {
        if (!errors.containsKey(field.getName())) {
            errors.put(field.getName(), value);
        }
    }
}
person Thomas Kläger    schedule 19.08.2016

Попробуйте сделать это:

String value = "null";
if(field.get(this) != null)
    value = field.get(this).toString();

Вместо этого:

String value = (String) field.get(this);
person NatNgs    schedule 18.08.2016
comment
Обратите внимание, что это может привести к ошибке, если field.get(this) равно null. Лучше использовать Objects.toString(field.get(this)). - person Andy Turner; 18.08.2016
comment
@AndyTurner, как может быть, что ты всегда рядом и прав, и все еще меньше 30 тысяч репу? :) - person xenteros; 18.08.2016
comment
Для достижения @xenteros 30k rep требуется 150 дней в день. Если бы я действительно пытался достичь этого, я сомневаюсь, что у меня все еще была бы работа :) - person Andy Turner; 18.08.2016
comment
@xenteros да, знаю. Нет, не знают. - person Andy Turner; 18.08.2016
comment
Спасибо @NathaëlNoguès. Это сработало. У вас есть идея, почему это сработало, когда я запустил модульный тест, но не сработало, когда я запустил покрытие? - person co.zohar; 18.08.2016
comment
@Co.zohar Я действительно понятия не имею, почему это сработало в модульных тестах, ха-ха! Я очень не понимаю, в чем на самом деле была ваша проблема, я просто попытался исправить распространенную ошибку Java (чтобы привести к String вместо использования метода toString) - person NatNgs; 18.08.2016
comment
Это не настоящее исправление. Настоящая проблема заключается в том, что ОП ожидает, что все его/ее поля будут строками. - person Oliver Charlesworth; 18.08.2016
comment
@OliverCharlesworth Спасибо. Я добавил проверку, является ли значение поля экземпляром String. - person co.zohar; 18.08.2016

Наконец, я проверил, что значение поля является экземпляром String, и заменил приведение к String функцией toString().

String value = null;
Object fieldValue = field.get(this);
if (fieldValue instanceof String) {
    value = fieldValue.toString();
}

if ("N".equals(value)) {
    if (!errors.containsKey(field.getName())) {
        errors.put(field.getName(), value);
    }
}
person co.zohar    schedule 18.08.2016