1

I'd like to determine whether all Optional members of an immutable are empty. Is there a way to do this automatically without checking all the known Optionals by hand?

I'm concerned that even if do write a check for each Optional member someone will come along later and add an Optional field without updating that method.

lf215
  • 1,185
  • 7
  • 41
  • 83
  • have you considered using reflection? I usually default to that when I have values that may be constantly being added or removed. Admittedly, I'm not familiar with the immutables library, but it seems checking by reflection could work, based on my quick glimpse. – Himself12794 Nov 09 '16 at 02:52
  • Reflection is certainly the main underlying mechanism to do it, but my question is more of whether there is a convenient, built-in way to do it. I would not want to implement this myself. One of the tricky things about Optionals with the immutables library is that they allow multiple types as Optionals. If I were to implement the check myself and then the library added another type as Optional, my method could become outdated. See [here](https://immutables.github.io/immutable.html#optional-attributes). – lf215 Nov 09 '16 at 02:57
  • Ah yes, I see your issue with that. If there's not a built-in way, perhaps a feature recommendation could be in order as a feature on the Github. Seems a bit too specific to pass though. – Himself12794 Nov 09 '16 at 03:02

1 Answers1

3

It may change in the future, but I think you can try take a look at the overloaded builder methods generated for optional members:

For an optional attribute named opt, where elements are of type T

opt(T) sets present value for T

opt(Optional<T>) specifies present or absent

A Example

SomeValue.java

@Value.Immutable
public abstract class SomeValue {

    public abstract int foo();
    public abstract Optional<Object> obj();
    public abstract com.google.common.base.Optional<Double> d();
}

TestImmutables.java

public class TestImmutables {
    public static void main(String [] args) {
        SomeValue someValue = ImmutableSomeValue.builder().foo(2).build();

        for (Method method : someValue.getClass().getDeclaredMethods()) {
            System.out.print(method.getName() + "(");
            for (Type t : method.getGenericParameterTypes()) {
                System.out.print(t);
                System.out.print(",");
            }
            System.out.println(")");
        }
    }
}

Output

Each line is a method, pay attention to the methods generated for optional members.

builder()
equalTo(class immutables.ImmutableSomeValue,)
withObj(class java.lang.Object,)                           < obj
withObj(java.util.Optional<java.lang.Object>,)             < obj
withD(com.google.common.base.Optional<java.lang.Double>,)  < d
withD(double,)                                             < d
d()
withFoo(int,)
foo()
obj()
equals(class java.lang.Object,)
toString()
hashCode()
copyOf(class immutables.SomeValue,)

Basically you are looking for two overloads, each with exactly one parameter, and if parameter type of one is T, the parameter type of the other is SomeOptional<T>.

Community
  • 1
  • 1
xiaofeng.li
  • 8,237
  • 2
  • 23
  • 30