2

I have an object with 3 attributes, where only one can be not null. I would like to call a methode with the argument that is not null but if possible without a large if else statement.

I thought of something like this, but it doesn't work.

myMethode(myObj.getAttr1() || myObj.getAttr2() || myObj.getAttr3());

What would be a good solution?

mxcx
  • 75
  • 8
  • 4
    Check [Multiple null checks in Java 8](https://stackoverflow.com/questions/54800817/multiple-null-checks-in-java-8) – ernest_k Jun 29 '21 at 08:56
  • Also, https://stackoverflow.com/questions/2768054/how-to-get-the-first-non-null-value-in-java – k314159 Jun 29 '21 at 10:58
  • If your object's attributes are so interrelated that one, and only one, of them will be non-null at any one time (an invariant condition), then you should consider adding a `getTheNonNullAttribute()` method to your object (suitably named, of course). – k314159 Jun 29 '21 at 11:00
  • @k314159 I can't do this because the classes are generated with JAXB – mxcx Jun 29 '21 at 11:23

3 Answers3

2

One option is to stream the attributes and filter the first (presumably, only) non-null one:

myMethod(Stream.of(myObj.getAttr1(), myObj.getAttr2(), myObj.getAttr3())
               .filter(Objects::notNull)
               .findFirst()
               .orElse(null) // Or perhaps throw an exception?
        );
Mureinik
  • 297,002
  • 52
  • 306
  • 350
  • getAttr1, getAttr2 and getAttr3 all return different classes, lets say class1, class2 and class3. Is there a way to have the return value of the Stream to be one of these classes and not Object? – mxcx Jun 29 '21 at 11:42
  • @mxcx The stream must return some common parent, since in compile time you don't know which of these will be null or not – Mureinik Jun 29 '21 at 11:54
1

|| is a logical or operator and can be used only between two boolean types, which is why your code doesn't work.

myMethode(myObj.getAttr1() != null ? myObj.getAttr1() : 
          myObj.getAttr2() != null ? myObj.getAttr2() : 
          myObj.getAttr3() != null ? myObj.getAttr3() : null);
gdrt
  • 3,160
  • 4
  • 37
  • 56
1

if your object only 3 attributes , you can use reflection like below

final long notNullAttributeCount = Arrays.stream(myObj.getClass().getFields())
        .map(f -> {
            try {
                f.setAccessible(true);
                return f.get(myObj);
            } catch (IllegalAccessException e) {
                return null;
            }
        }).filter(Objects::nonNull).count();

if (notNullAttributeCount == 1) {
    //do your staff
}
divilipir
  • 882
  • 6
  • 17