Reputation: 740
I have this function and it returns an object because it has no ideas what the return could be. It could be in long, int, String, or 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);
}
How do I use this function to assign a variable to an int, long or Foo? This is what I currently have:
long someUid = (long) getRequestByFieldName("some_uid").orElse(0);
However, I keep getting this error if the field was missing:
java.util.Optional cannot be cast to java.lang.Long
Upvotes: 1
Views: 6199
Reputation: 46181
If the field is not present you end up assigning Optional.empty()
to the fieldValue
variable.
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
You then return with return Optional.of(fieldValue)
. This means, when no field is found, you return an Optional<Optional<?>>
so when doing the following:
long someUid = (long) getRequestByFieldName("some_uid").orElse(0);
The orElse
bit is never called because the Optional
is never empty. Instead, it holds an Optional
which obviously can't be cast to Long
. From your code, you should be able to simply return the result of map
, like so:
return objectMap.entrySet().stream()
.filter(fieldDescriptorObjectEntry -> {
Descriptors.FieldDescriptor descriptor = fieldDescriptorObjectEntry.getKey();
return descriptor.getName().equals(fieldName);
})
.findFirst()
.map(fieldDescriptorObjectEntry -> fieldDescriptorObjectEntry.getValue());
Whether or not this completely solves the casting problem depends on how you determine what type of object the Optional
holds.
Upvotes: 4