1

私は現在XMLファイルを使用しており、try/catchブロックを適切に回避するためのより良い方法を探しています。

これがそのことです。XMLファイルがあるとしましょう。

<A>
    <BB>37</BB>
    <CC>
        <DDD>1</DDD>
    </CC>
</A> 

実際、これをオブジェクトに変換します。つまり、 myXml.getA()などを実行できます。

私のコードでは、このオブジェクト内の特定の要素をたくさん検索します。つまり、次のような行がたくさんあります。

int ddd = myXml.getA().getCC().getDDD();

重要なのは、一部の要素が存在しない可能性があることです。たとえば、別のXML要素は次のようになります。

<A'>
    <BB'>37</BB'>
</A'> 

したがって、dddを取得しようとすると、getCC()NullPointerExceptionを発生させます。

結局、私はそれをそのようにコーディングすることになります:

int ddd;
try{
    ddd = myXml.getA().getCC().getDDD();
}
catch (NullPointerException e){
ddd = 0;
}

これは機能しますが、コードは本当に醜くなります。私は次のようなものを持つための解決策を探しています

int ddd = setInt(myXml.getA().getCC().getDDD(), 0);

メソッドが例外を発生させた場合のデフォルトは0です。

それを行うための良い方法はありますか?

今まで、エラーを起こさない解決策を見つけることができませんでした。

あなたの助けのためのThx!

編集: XML関連の回答を得ないようにしてください。みんなが問題を理解できるようにxmlの部分を見せました。私のコードでは、XMLにアクセスできませんが、XMLを表すオブジェクトのみにアクセスできます。

簡単に言うと、私が本当に気に入っているのは、ゲッターをテストするためのある種のisNullメソッドです。

4

7 に答える 7

2

Nullオブジェクトパターンを見ることができます。

例えば ​​:

public class A {
    private C c;
    public C getC() {
        if (c == null) {
            c = new C(0); // the "null object"
        }
        return c;
    }
}

public class C {
    private int d;
    public C(int d) {
        this.d = d;
    }

    public int getD() {
        return d;
    }
}

しかし、個人的には、私はこのコードに悪い気持ちを持っています:

int ddd = myXml.getA().getCC().getDDD();

これはデメテルの法則に強く違反しています。クラスの呼び出し元は、A、C、およびDに関する知識が多すぎます。このコードは、適応および保守が明らかに困難です。

于 2012-09-07T13:48:57.087 に答える
2

これは、jaxbを使用する際の煩わしさのようなものです。私の会社では、jaxbで十分な作業を行っているため、重要な値に対してnull以外の値を返すことが保証されているすべてのゲッターの「安全な」バージョンを生成するxjcプラグインを作成する価値があります(サブオブジェクトは実際には存在しませんでした)。

生成されたモデルエンティティの例を次に示します。

public class ExampleUser implements Serializable {
    private final static long serialVersionUID = 20090127L;
    @XmlAttribute
    protected String name;
    @XmlAttribute
    protected String email;
    public final static ExampleUser EMPTY_INSTANCE = new ExampleUser() {
        private static final long serialVersionUID = 0L;
        @Override
        public void setName(java.lang.String value) { throw new UnsupportedOperationException(); }
        @Override
        public void setEmail(java.lang.String value) { throw new UnsupportedOperationException(); }
    };

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String value) {
        this.email = value;
    }
}

public class ExampleAccount implements Serializable {
    private final static long serialVersionUID = 20090127L;
    protected ExampleUser user;
    @XmlElement(name = "alias")
    protected List<String> aliases;
    @XmlAttribute
    protected String id;
    @XmlAttribute
    protected String name;
    public final static ExampleAccount EMPTY_INSTANCE = new ExampleAccount() {
        private static final long serialVersionUID = 0L;
        @Override
        public void setUser(com.boomi.platform.api.ExampleUser value) { throw new UnsupportedOperationException(); }
        @Override
        public List<String> getAliases() { return java.util.Collections.emptyList(); }
        @Override
        public void setId(java.lang.String value) { throw new UnsupportedOperationException(); }
        @Override
        public void setName(java.lang.String value) { throw new UnsupportedOperationException(); }
    };

    public ExampleUser getUser() {
        return user;
    }

    public void setUser(ExampleUser value) {
        this.user = value;
    }

    public List<String> getAliases() {
        if (aliases == null) {
            aliases = new ArrayList<String>();
        }
        return this.aliases;
    }

    public String getId() {
        return id;
    }

    public void setId(String value) {
        this.id = value;
    }

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public ExampleUser safeGetUser() {
        return (getUser() != null) ? getUser() : ExampleUser.EMPTY_INSTANCE;
    }
}

したがって、NPEを恐れることなくこのコードを書くことができます。

userEmail = account.safeGetUser().getEmail();
于 2012-09-07T13:54:32.300 に答える
1

この種の問題に対する2つの一般的なアプローチは、他の回答ですでにカバーされているnullオブジェクトパターンと、Scalaのオプションなどの安全なnullを入力することです。

http://www.scala-lang.org/api/current/scala/Option.html

OptionのJavaバージョンがいくつかあります。

http://functionaljava.googlecode.com/svn/artifacts/2.20/javadoc/fj/data/Option.html

http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/base/Optional.html

フラットマップと組み合わせると、タイプセーフヌルが特に役立ちます。

于 2012-09-07T14:01:59.117 に答える
1

Apache common-beanutilsを使用して、setメソッドを作成します。リフレクションを使用するため、エラーをキャッチする場所は1つだけです。

これは次のようになります(コード化されていないため、構文エラーが発生します)。

int getInt(Object root, String beanPattern, int defaultValue)
{
   try
   {
      return PropertyUtils.getNestedProperty(root, beanPattern);
   }
   catch (Exception e)
   {
      return 0;
   }
}

これはそのように呼ばれるでしょう。

int ddd = getInt(myXml, "A.CC.DDD", 0);
于 2012-09-07T14:20:33.233 に答える
0

値ごとに呼び出されるほど一般的で、値または0を返す関数を作成することはできません。

何かのようなもの

myGetSomething(FOO){
  try {getFOO} catch ...
}

そうすれば、コード自体は見栄えがしますが、関数には基本的に呼び出しごとにtry-catchがあります。

于 2012-09-07T13:32:42.210 に答える
0

getメソッドの代わりにXpathクエリを使用します。要素のパスが見つからない場合は、空のリストが表示されます。

List ddds = myXml.query("/AA/BB/CC/DDD");
if (!ddds.empty()) {}

正しい構文は、使用するXMLライブラリによって異なります。

于 2012-09-07T13:37:39.343 に答える
0

コードの一部をGroovyまたはXtendで記述します; どちらも、式の左側の?.戻り値がに評価される構文をサポートしています。彼らはまたあなたが書くことができるように役に立たないものを取り除きます:nullnullget

myXml.a?.cc?.ddd

Xtendの構文はGroovyと比較すると劣りますが、プレーンJavaにコンパイルされるため、結果を使用するには、いくつかのヘルパークラスを含む単一のJARをコードに追加する必要があります。

于 2012-09-07T14:12:57.847 に答える