Java 8 Casting Необязательно <Object>в long, int, String или Foo - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть эта функция, и она возвращает объект, потому что не знает, каким может быть возвращение.Это может быть long, int, String или Foo

@SuppressWarnings("unchecked")
public Optional<Object> getRequestByFieldName(String fieldName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
    Class<?> classA = instanceA.getClass();

    Method method = classA.getMethod("getAllFields");

    Object o =  method.invoke(instanceA);

    // I'm using protobuf to get the field value,
    // but a field could be missing because someone didn't send it
    // in that case I return an Optional Empty object
    Map<Descriptors.FieldDescriptor, Object> objectMap = (Map) o;

    Object fieldValue =  objectMap.entrySet().stream()
            .filter(fieldDescriptorObjectEntry -> {
                Descriptors.FieldDescriptor descriptor = fieldDescriptorObjectEntry.getKey();
                return descriptor.getName().equals(fieldName);
            })
            .findFirst().map(fieldDescriptorObjectEntry -> fieldDescriptorObjectEntry.getValue())
            .orElse(Optional.empty());

    return Optional.of(fieldValue);
}

Как я могу использовать эту функцию для присвоения переменной int, long или Foo?Это то, что у меня сейчас есть:

long someUid = (long) getRequestByFieldName("some_uid").orElse(0);

Однако, я получаю эту ошибку, если поле отсутствует:

java.util.Optional cannot be cast to java.lang.Long

1 Ответ

0 голосов
/ 28 декабря 2018

Если поле отсутствует, вы в конечном итоге присваиваете Optional.empty() переменной fieldValue.

Object fieldValue =  objectMap.entrySet().stream()
        .filter(fieldDescriptorObjectEntry -> {
            Descriptors.FieldDescriptor descriptor = fieldDescriptorObjectEntry.getKey();
            return descriptor.getName().equals(fieldName);
        })
        .findFirst().map(fieldDescriptorObjectEntry -> fieldDescriptorObjectEntry.getValue())
        .orElse(Optional.empty()); // ISSUE HERE

Затем вы возвращаетесь с return Optional.of(fieldValue).Это означает, что когда поле не найдено, вы возвращаете Optional<Optional<?>>, поэтому при выполнении следующих действий:

long someUid = (long) getRequestByFieldName("some_uid").orElse(0);

Бит orElse равен , никогда вызывается, поскольку Optionalникогда не пустоВместо этого он содержит Optional, который явно не может быть приведен к Long.Из вашего кода вы сможете просто вернуть результат map, например, так:

return objectMap.entrySet().stream()
        .filter(fieldDescriptorObjectEntry -> {
            Descriptors.FieldDescriptor descriptor = fieldDescriptorObjectEntry.getKey();
            return descriptor.getName().equals(fieldName);
        })
        .findFirst()
        .map(fieldDescriptorObjectEntry -> fieldDescriptorObjectEntry.getValue());

То, полностью ли это решает проблему приведения, зависит от того, как вы определяете, какой тип объекта Optional держит.

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