class Foo{
Bar bar;
}
class Bar{
Baz baz;
}
class Baz{
Qux qux;
}
class Qux{
String hoge;
}
たとえば、上記のようなクラスがあったとして、fooオブジェクトからhogeフィールドにアクセスしたい、なんていうとき。
もし、fooからquxまでひいていく途中のいずれかのフィールドがnullかもしれないとしたら、NullPointerExceptionが発生してしまう。
public class Main {
public static void main(String[] args) {
Foo foo = getFoo();
System.out.println(foo.bar.baz.qux.hoge);
// たとえばbazがnullならNullPointerExceptionが発生する
}
}
なので、どれもnullになる可能性があるなら、
public class Main {
public static void main(String[] args) {
Foo foo = getFoo();
if(foo != null){
if(foo.bar != null){
if(foo.bar.baz != null){
if(foo.bar.baz.qux != null){
System.out.println(foo.bar.baz.qux.hoge);
}
}
}
}
}
}
こう書けば安心ですね。
いやいやいや。
私はそんなの耐えられない。。。
public class Main {
public static void main(String[] args) {
Foo foo = getFoo();
String hoge = get(foo, "bar.baz.qux.hoge", String.class);
System.out.println(hoge);
}
public static <T> T get(Object src, String access, Class<T> type){
String[] paths = access.split("\\.");
Object cursor = src;
try {
for (String fieldName : paths) {
Field field = cursor.getClass().getDeclaredField(fieldName);
Object obj = field.get(cursor);
if (obj == null) {
return null;
}
cursor = obj;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
if(cursor != null && type.isInstance(cursor)){
return type.cast(cursor);
}
return null;
}
}
だからこんな感じで解決しました。
リフレクションつかってフィールド毎にnullチェックする…!(力技)
入力支援が効かないとか色々な犠牲もありますが、 if文の入れ子になるよりは読みやすく、精神衛生上も良い気がします。たぶん。