What is the best practice for referencing nested objects?
Say I have the following:
class Outer {
private InnerA innerA;
//getters and setters
}
class InnerA {
private InnerB innerB;
//getters and setters
}
class InnerB {
private String someString;
//getters and setters
}
and in my controller or service class I need to check the someString String variable of the InnerB class to make sure it is not null or not empty so I do this:
if (getOuter().getInnerA().getInnerB().getSomeString() != null && !getOuter().getInnerA().getInnerB().getSomeString().equalsIgnoreCase("") {
//do something
}
To me this looks messy and could have issues if the nested objects themselves are null.
Do I create getters ans setters in the parent objects for the child objects checking for null? Just wondering what the best practice was if any and/or what some of you do in your code?
I don't think users of Outer should have knowledge of Outer.InnerA.InnerB.SomeString - it's buried to deep. You can't change implementation of InnerB without touching clients of Outer 3 levels separated - so what's the point of even having inner classes? Situations like you're describing are ugly and shouldn't arise.
I'd recommend you first consider whether SomeString belongs in InnerB or InnerA or Outer.
Now suppose your hierarchy is correct, yet SomeString has this unique property of being required by clients of Outer (if SomeString is not unique that way, hierarchy is definitely wrong). In this case, Outer.getSomeString(), or better yet, Outer.isSomeStringNullOrEmpty(), so that at least clients of Outer don't have to know about InnerA and InnerB
PS. someString.equalsIgnoreCase("") is expensive, don't use that. Much cheaper is someString.length() == 0
My belief is that you should not expose "inner-inner" members through methods of the outer class unless you are adding some sort of functionality or different behaviour to them or the value is "essential" to the use of the outer class. However this is also a matter of judgement and can vary depending on the use and architecture of your code.
On a side note if you want the code for a long string of invocations to be "less ugly" I suggest voting for addition of the Elvis Operator for project coin in the next version of Java (I wish it had made it into 7 :-().
I would recommend reading up on the Law of Demeter.
It's messy, but if you only had to do it in one place then I might live with it. Otherwise, I'd implement a
Outer.getSomeString()
that hides the internal path, since your Outer class is the one you're exposing as your interface.This also allows you to deal with a case where one of the intermediary inner classes is null, without having to do a number of sequential checks each time you try to access
someString
.This is a java limitation. You should implement helper methods in the parent "OuterObject" if it helps you to reduce code duplication.
This helper methods are useful for object which are aggregating other object and you need to check only if the nested value exists.
Code:
Which would do all the null checks.
This problem occurs often with objects generated from *.xsd. In a complicated xml structure it happens often that there a many nested optional nodes. And what usually is interesting is the last node. Then its better to write helper methods which will answer the questions if node exists for reuse.
If it comes up to your cod sample i usually write something like that
I've written a Java 8 Method:
Now you can call:
If
myObject.getSomeOtherObject()
isnull
the method will returnnull
, else it will callmyObject.getSomeOtherObject().toString()
.That's pretty useful, if you just have to go one level deeper.
For multi level, it gets ugly: