4279

私はobject != null避けるためにたくさん使いますNullPointerException

次の代替手段は何ですか:

if (someobject != null) {
    someobject.doCalc();
}
4

65 に答える 65

2785

これは私には、中級から中級の開発者がいつか直面する傾向があるかなり一般的な問題のように聞こえます。彼らは参加している契約を知らないか信頼せず、防御的にnullをオーバーチェックします。さらに、独自のコードを作成する場合、何かを示すためにnullを返すことに依存する傾向があるため、呼び出し元はnullをチェックする必要があります。

別の言い方をすれば、nullチェックが発生する2つのインスタンスがあります。

  1. nullは、契約に関して有効な応答です。と

  2. 有効な応答ではない場合。

(2)簡単です。ステートメント(アサーション)を使用するassertか、失敗を許可します(たとえば、 NullPointerException)。アサーションは、1.4で追加された非常に使用されていないJava機能です。構文は次のとおりです。

assert <condition>

また

assert <condition> : <object>

ここ<condition>で、はブール式であり、はメソッドの出力がエラーに含まれる<object>オブジェクトです。toString()

条件が真でない場合、ステートメントは()をスローassertします。デフォルトでは、Javaはアサーションを無視します。オプションをJVMに渡すことにより、アサーションを有効にできます。個々のクラスおよびパッケージのアサーションを有効または無効にできます。これは、開発およびテスト中にアサーションを使用してコードを検証し、本番環境でそれらを無効にできることを意味しますが、私のテストでは、アサーションによるパフォーマンスへの影響はほとんどありません。ErrorAssertionError-ea

この場合、アサーションを使用しなくても問題ありません。コードが失敗するだけなので、これはアサーションを使用した場合に発生します。唯一の違いは、アサーションを使用すると、より意味のある方法で、場合によっては追加の情報を使用して、より早く発生する可能性があることです。これは、予期していなかった場合に発生した理由を理解するのに役立ちます。

(1)少し難しいです。呼び出しているコードを制御できない場合は、行き詰まります。nullが有効な応答である場合は、それを確認する必要があります。

ただし、自分で制御するコードの場合(これはよくあることですが)、話は別です。応答としてnullを使用することは避けてください。コレクションを返すメソッドを使用すると、簡単です。ほとんどの場合、nullの代わりに空のコレクション(または配列)を返します。

非コレクションの場合、それは難しいかもしれません。これを例として考えてみましょう。これらのインターフェイスがある場合:

public interface Action {
  void doSomething();
}

public interface Parser {
  Action findAction(String userInput);
}

ここで、Parserは生のユーザー入力を受け取り、何かを行うためのコマンドラインインターフェイスを実装している場合など、実行するものを見つけます。これで、適切なアクションがない場合にnullを返すというコントラクトを作成できます。それはあなたが話しているヌルチェックにつながります。

別の解決策は、nullを返さず、代わりにNullObjectパターンを使用することです。

public class MyParser implements Parser {
  private static Action DO_NOTHING = new Action() {
    public void doSomething() { /* do nothing */ }
  };

  public Action findAction(String userInput) {
    // ...
    if ( /* we can't find any actions */ ) {
      return DO_NOTHING;
    }
  }
}

比較:

Parser parser = ParserFactory.getParser();
if (parser == null) {
  // now what?
  // this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
  // do nothing
} else {
  action.doSomething();
}

ParserFactory.getParser().findAction(someInput).doSomething();

これは、より簡潔なコードにつながるため、はるかに優れた設計です。

とはいえ、findAction()メソッドが意味のあるエラーメッセージを含む例外をスローすることはおそらく完全に適切です。特に、ユーザー入力に依存している場合はそうです。findActionメソッドが例外をスローする方が、呼び出し元のメソッドが説明のない単純なNullPointerExceptionで爆破するよりもはるかに優れています。

try {
    ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
    userConsole.err(anfe.getMessage());
}

または、「何もしない」ではなく、「試行/キャッチ」メカニズムが醜すぎると思われる場合は、デフォルトのアクションでユーザーにフィードバックを提供する必要があります。

public Action findAction(final String userInput) {
    /* Code to return requested Action if found */
    return new Action() {
        public void doSomething() {
            userConsole.err("Action not found: " + userInput);
        }
    }
}
于 2008-11-07T12:06:40.507 に答える
691

JetBrains IntelliJ IDEAEclipse 、NetbeansなどのJava IDE、またはfindbugsなどのツールを使用している(または使用を計画している)場合は、アノテーションを使用してこの問題を解決できます。

基本的に、あなたはとを持ってい@Nullableます@NotNull

次のように、メソッドとパラメータで使用できます。

@NotNull public static String helloWorld() {
    return "Hello World";
}

また

@Nullable public static String helloWorld() {
    return "Hello World";
}

2番目の例はコンパイルされません(IntelliJ IDEAで)。

helloWorld()別のコードで最初の関数を使用する場合:

public static void main(String[] args)
{
    String result = helloWorld();
    if(result != null) {
        System.out.println(result);
    }
}

これで、IntelliJ IDEAコンパイラは、helloWorld()関数が返されないため、チェックが役に立たないことを通知しますnull

パラメータを使用する

void someMethod(@NotNull someParameter) { }

あなたが次のようなものを書く場合:

someMethod(null);

これはコンパイルされません。

を使用した最後の例@Nullable

@Nullable iWantToDestroyEverything() { return null; }

これを行う

iWantToDestroyEverything().something();

そして、あなたはこれが起こらないことを確信することができます。:)

これは、コンパイラーに通常よりも多くのことをチェックさせ、コントラクトをより強力にするための優れた方法です。残念ながら、すべてのコンパイラでサポートされているわけではありません。

IntelliJ IDEA 10.5以降では、他の@Nullable @NotNull実装のサポートが追加されました。

ブログ投稿を参照してください。より柔軟で構成可能な@Nullable/@NotNullアノテーション

于 2010-03-05T10:31:19.393 に答える
346

null 値が許可されていない場合

メソッドが外部から呼び出される場合は、次のように開始します。

public void method(Object object) {
  if (object == null) {
    throw new IllegalArgumentException("...");
  }

object次に、そのメソッドの残りの部分で、それが nullではないことがわかります。

内部メソッド (API の一部ではない) である場合は、null にすることはできないことを文書化するだけです。

例:

public String getFirst3Chars(String text) {
  return text.subString(0, 3);
}

ただし、メソッドが値を渡すだけで、次のメソッドがそれを渡すなどの場合、問題が発生する可能性があります。その場合、上記のように引数を確認することをお勧めします。

null が許可されている場合

これは本当に依存します。私がよくこのようなことをしていることがわかったら:

if (object == null) {
  // something
} else {
  // something else
}

だから私は分岐し、2 つのまったく異なることを行います。データに応じて 2 つの異なることを行う必要があるため、醜いコード スニペットはありません。たとえば、入力を処理する必要がありますか、それとも適切なデフォルト値を計算する必要がありますか?


私がイディオム「if (object != null && ...」を使うことは実際にはまれです。

イディオムを通常使用する場所の例を示すと、例を挙げたほうが簡単かもしれません。

于 2008-11-07T09:27:00.250 に答える
249

うわー、私は57の異なる推奨方法があるときに別の答えを追加するのはほとんど嫌いですがNullObject pattern、この質問に興味のある人は、Java7に「null-safe」を追加する提案があることを知りたいと思うかもしれません。処理」 —if-not-equal-nullロジックの合理化された構文。

AlexMillerの例は次のようになります。

public String getPostcode(Person person) {  
  return person?.getAddress()?.getPostcode();  
}  

?.、左側の識別子がnullでない場合にのみ参照を解除し、そうでない場合は式の残りの部分を。として評価しnullます。JavaPosseのメンバーであるDickWallやDevoxxの有権者のように、この提案を本当に気に入っている人もいますが、実際にはnull番兵としての使用を促進するという理由で反対意見もあります。


更新: Java7のヌルセーフオペレーターの公式提案がProjectCoinの下に提出されました。構文は上記の例とは少し異なりますが、同じ概念です。


更新:ヌルセーフオペレーターの提案は、プロジェクトコインに組み込まれませんでした。したがって、Java7ではこの構文は表示されません。

于 2009-01-17T05:08:35.463 に答える
207

未定義の値が許可されていない場合:

null 参照解除の可能性について警告するように IDE を構成できます。たとえば、Eclipse では、Preferences > Java > Compiler > Errors/Warnings/Null analysisを参照してください。

未定義の値が許可されている場合:

未定義の値が意味を持つ新しい API を定義する場合は、オプション パターンを使用します(関数型言語でおなじみかもしれません)。次の利点があります。

  • 入力または出力が存在するかどうかは、API で明示的に記述されています。
  • コンパイラは、「未定義」のケースを処理することを強制します。
  • Option はmonad であるため、詳細な null チェックは必要ありません。 map/foreach/getOrElse または同様のコンビネータを使用して値を安全に使用してください(例)

Java 8 には組み込みOptionalクラスがあります (推奨)。以前のバージョンでは、 GuavaOptionalFunctionalJavaなどの代替ライブラリがありますOption。しかし、多くの関数型スタイルのパターンと同様に、Java で Option を使用すると (8 であっても) かなりのボイラープレートが生成されます。これは、Scala や Xtend などのより冗長でない JVM 言語を使用して減らすことができます。

nulls を返す可能性のある API を処理する必要がある場合、Java では多くのことを行うことができません。Xtend と Groovy にはElvis operator ?:null-safe dereference operator ?.がありますが、これは null 参照の場合は null を返すため、null の適切な処理を「延期」するだけであることに注意してください。

于 2010-01-14T13:45:06.277 に答える
204

この状況のた​​めだけに -

equals メソッドを呼び出す前に変数が null かどうかをチェックしない (以下の文字列比較の例):

if ( foo.equals("bar") ) {
 // ...
}

存在しない場合NullPointerExceptionになります。foo

String次のように sを比較すると、それを回避できます。

if ( "bar".equals(foo) ) {
 // ...
}
于 2008-11-09T12:24:58.347 に答える
179

Java 8 ではjava.util.Optional、おそらく問題の一部を解決する新しいクラスが登場します。少なくとも、コードの可読性が向上し、パブリック API の場合は、API の契約がクライアント開発者にとってより明確になると言えます。

それらは次のように機能します。

特定の型 ( ) のオプション オブジェクトFruitは、メソッドの戻り値の型として作成されます。空にすることも、Fruitオブジェクトを含めることもできます。

public static Optional<Fruit> find(String name, List<Fruit> fruits) {
   for (Fruit fruit : fruits) {
      if (fruit.getName().equals(name)) {
         return Optional.of(fruit);
      }
   }
   return Optional.empty();
}

次に、特定の Fruit インスタンスのFruit( )のリストを検索するこのコードを見てください。fruits

Optional<Fruit> found = find("lemon", fruits);
if (found.isPresent()) {
   Fruit fruit = found.get();
   String name = fruit.getName();
}

演算子を使用してmap()、オプションのオブジェクトに対して計算を実行したり、値を抽出したりできます。 orElse()欠損値のフォールバックを提供できます。

String nameOrNull = find("lemon", fruits)
    .map(f -> f.getName())
    .orElse("empty-name");

もちろん、null/空の値のチェックは引き続き必要ですが、少なくとも開発者は値が空の可能性があることを認識しており、チェックを忘れるリスクは限定的です。

Optional戻り値が空の可能性がある場合は常に使用し、そうでない場合にのみプレーン オブジェクトを返す(規則)を使用してゼロから構築された APInullでは、クライアント コードは単純なオブジェクトの戻り値の null チェックを放棄する可能性があります...

もちろんOptional、メソッドの引数として使用することもできます。場合によっては、5 つまたは 10 個のオーバーロード メソッドよりもオプションの引数を示す方がよいでしょう。

OptionalorElseは、デフォルト値の使用を可能にしたり、ラムダ式ifPresentで機能するなど、他の便利なメソッドを提供します。

この記事(この回答を書くための私の主な情報源)を読むことをお勧めします。この記事では、NullPointerException問題のある(および一般的にはヌルポインター)と、によってもたらされる(部分的な)解決策Optionalがよく説明されています:Java Optional Objects

于 2013-04-25T15:22:50.317 に答える
130

チェックしているオブジェクトの種類に応じて、次のような apache commons のクラスの一部を使用できる場合があります: apache commons langおよびapache commons collections

例:

String foo;
...
if( StringUtils.isBlank( foo ) ) {
   ///do something
}

または(チェックする必要があるものに応じて):

String foo;
...
if( StringUtils.isEmpty( foo ) ) {
   ///do something
}

StringUtils クラスは数あるクラスの 1 つにすぎません。コモンズには、null 安全な操作を行う優れたクラスがかなりあります。

以下は、Apache ライブラリ (commons-lang-2.4.jar) を含めるときに Java で null 検証を使用する方法の例です。

public DOCUMENT read(String xml, ValidationEventHandler validationEventHandler) {
    Validate.notNull(validationEventHandler,"ValidationHandler not Injected");
    return read(new StringReader(xml), true, validationEventHandler);
}

また、Spring を使用している場合は、Spring のパッケージにも同じ機能があります。library(spring-2.4.6.jar) を参照してください。

この static classf を spring(org.springframework.util.Assert) から使用する方法の例

Assert.notNull(validationEventHandler,"ValidationHandler not Injected");
于 2008-11-07T09:10:19.657 に答える
102
  • オブジェクトが null であってはならない (またはそれがバグである) と考えられる場合は、アサートを使用します。
  • メソッドがnullパラメータを受け入れない場合は、javadocでそれを言って、アサートを使用してください。

オブジェクトが null である可能性があるケースを処理したい場合にのみ、オブジェクト != null をチェックする必要があります...

null / notnull パラメータをサポートするために Java7 に新しいアノテーションを追加する提案があります: http://tech.puredanger.com/java7/#jsr308

于 2008-11-07T08:55:26.053 に答える
93

私は「フェイル ファスト」コードのファンです。自問してみてください - パラメータが null の場合に役立つことをしていますか? その場合にコードが何をすべきかについて明確な答えがない場合...つまり、最初からnullであってはならず、それを無視して NullPointerException がスローされるようにします。呼び出し元のコードは、IllegalArgumentException の場合と同じように NPE を理解しますが、開発者にとっては、コードが他の予期しない不測の事態を実行しようとするよりも、NPE がスローされた場合の方が、デバッグして何が問題なのかを理解しやすくなります。ロジック - いずれにせよ、最終的にはアプリケーションが失敗します。

于 2011-05-23T18:18:14.057 に答える
81

Null オブジェクト パターン (用途がある) ではなく、null オブジェクトがバグである状況を考えることができます。

例外がスローされたら、スタック トレースを調べてバグを解決します。

于 2008-11-07T08:50:24.503 に答える
80

場合によっては、対称操作を定義するパラメーターを操作するメソッドがあります。

a.f(b); <-> b.f(a);

b が null にならないことがわかっている場合は、単に交換できます。equals の場合に最も役立ちます。foo.equals("bar");より良い doの代わりに"bar".equals(foo);

于 2008-11-07T09:04:11.573 に答える
79

Google のコレクション フレームワークは、null チェックを実現する優れた洗練された方法を提供します。

次のようなライブラリ クラスにメソッドがあります。

static <T> T checkNotNull(T e) {
   if (e == null) {
      throw new NullPointerException();
   }
   return e;
}

使用法は次のとおりです ( を使用import static):

...
void foo(int a, Person p) {
   if (checkNotNull(p).getAge() > a) {
      ...
   }
   else {
      ...
   }
}
...

またはあなたの例では:

checkNotNull(someobject).doCalc();
于 2008-12-29T13:50:07.533 に答える
75

Null は「問題」ではありません。これは、完全なモデリング ツール セットの不可欠な部分です。ソフトウェアは世界の複雑さをモデル化することを目指しており、null はその負担を負います。Null は、Java などで「データなし」または「不明」を示します。したがって、これらの目的にはヌルを使用するのが適切です。「Null オブジェクト」パターンは好きではありません。「守護者を誰が守るのか」という問題が生じると思います。
私のガールフレンドの名前は何ですかと聞かれたら、私にはガールフレンドがいないと答える. Java 言語では null を返します。別の方法は、意味のある例外をスローして、できない(またはしない)問題を示すことです。

  1. 「不明な質問」に対しては、「不明な回答」を入力してください。(これがビジネスの観点から正しい場合は null セーフである必要があります) 使用前にメソッド内で一度 null の引数をチェックすると、複数の呼び出し元が呼び出し前に引数をチェックする必要がなくなります。

    public Photo getPhotoOfThePerson(Person person) {
        if (person == null)
            return null;
        // Grabbing some resources or intensive calculation
        // using person object anyhow.
    }
    

    上記は、私の写真ライブラリから存在しないガールフレンドの写真を取得しないという通常のロジック フローにつながります。

    getPhotoOfThePerson(me.getGirlfriend())
    

    そして、それは新しく登場するJava APIに適合します(楽しみにしています)

    getPhotoByName(me.getGirlfriend()?.getName())
    

    誰かのためにDBに保存された写真を見つけないのはむしろ「通常のビジネスフロー」ですが、私は他の場合に以下のようなペアを使用していました

    public static MyEnum parseMyEnum(String value); // throws IllegalArgumentException
    public static MyEnum parseMyEnumOrNull(String value);
    

    入力すること (Eclipse で javadoc を生成すること) を嫌い、<alt> + <shift> + <j>パブリック API のために 3 つの追加の単語を記述することも避けてください。ドキュメントを読まない人以外には、これで十分です。

    /**
     * @return photo or null
     */
    

    また

    /**
     * @return photo, never null
     */
    
  2. これはかなり理論的なケースであり、ほとんどの場合、Java null safe API を優先する必要があります (さらに 10 年以内にリリースされる場合に備えて) がNullPointerExceptionException. したがってThrowable、妥当なアプリケーションがキャッチする可能性がある条件を示す形式です ( javadoc )! 例外の最初の最大の利点を使用し、エラー処理コードを「通常の」コードから分離するには ( Java の作成者によると)、私の場合は catch が適切ですNullPointerException

    public Photo getGirlfriendPhoto() {
        try {
            return appContext.getPhotoDataSource().getPhotoByName(me.getGirlfriend().getName());
        } catch (NullPointerException e) {
            return null;
        }
    }
    

    疑問が生じる可能性があります:

    getPhotoDataSource()Q. null を返すとどうなりますか?
    A. ビジネスロジック次第です。フォト アルバムが見つからない場合は、写真を表示しません。appContext が初期化されていない場合はどうなりますか? このメソッドのビジネス ロジックはこれに耐えます。同じロジックをより厳密にする必要がある場合は、例外をスローします。これはビジネス ロジックの一部であり、null の明示的なチェックを使用する必要があります (ケース 3)。新しい Java Null-safe APIは、プログラマ エラーの場合にフェイル ファストになるように初期化されることを意味するものと意味しないものを選択的に指定するために、ここでより適切に適合します。

    Q. 冗長なコードが実行され、不要なリソースが取得される可能性があります。
    A.getPhotoByName()データベース接続を開き、PreparedStatement最後に人物名を作成して SQL パラメータとして使用しようとすると、発生する可能性があります。ここでは、未知の質問に対するアプローチが未知の答えを与える(ケース 1) が機能します。リソースを取得する前に、メソッドはパラメーターをチェックし、必要に応じて「不明」の結果を返す必要があります。

    Q. このアプローチでは、try クロージャが開くため、パフォーマンスが低下します。
    A. ソフトウェアは、まず理解しやすく、変更しやすいものでなければなりません。この後になって初めて、必要な場合にのみパフォーマンスについて考えることができます! そして必要なところに!(ソース)、および他の多く)。

    PS。このアプローチは、「通常の」コード原則とは別のエラー処理コードがどこかで使用するのに合理的であるのと同じくらい合理的に使用できます。次の例を考えてみましょう。

    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        try {
            Result1 result1 = performSomeCalculation(predicate);
            Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
            Result3 result3 = performThirdCalculation(result2.getSomeProperty());
            Result4 result4 = performLastCalculation(result3.getSomeProperty());
            return result4.getSomeProperty();
        } catch (NullPointerException e) {
            return null;
        }
    }
    
    public SomeValue calculateSomeValueUsingSophisticatedLogic(Predicate predicate) {
        SomeValue result = null;
        if (predicate != null) {
            Result1 result1 = performSomeCalculation(predicate);
            if (result1 != null && result1.getSomeProperty() != null) {
                Result2 result2 = performSomeOtherCalculation(result1.getSomeProperty());
                if (result2 != null && result2.getSomeProperty() != null) {
                    Result3 result3 = performThirdCalculation(result2.getSomeProperty());
                    if (result3 != null && result3.getSomeProperty() != null) {
                        Result4 result4 = performLastCalculation(result3.getSomeProperty());
                        if (result4 != null) {
                            result = result4.getSomeProperty();
                        }
                    }
                }
            }
        }
        return result;
    }
    

    PPS。反対票を投じるのが早い(そしてドキュメントを読むのがそれほど速くない)人のために、私は人生でヌルポインター例外(NPE)をキャッチしたことがないと言いたいです。しかし、NPE は のサブクラスであるため、この可能性は Java 作成者によって意図的に設計さExceptionれました。Java の歴史にThreadDeathは、Error実際にはアプリケーション エラーではなく、キャッチされることを意図していなかったという前例があります。ErrorよりもNPEがどれだけ適合するかThreadDeath!そうではありません。

  3. ビジネス ロジックが意味する場合にのみ、「データなし」をチェックします。

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person != null) {
            person.setPhoneNumber(phoneNumber);
            dataSource.updatePerson(person);
        } else {
            Person = new Person(personId);
            person.setPhoneNumber(phoneNumber);
            dataSource.insertPerson(person);
        }
    }
    

    public void updatePersonPhoneNumber(Long personId, String phoneNumber) {
        if (personId == null)
            return;
        DataSource dataSource = appContext.getStuffDataSource();
        Person person = dataSource.getPersonById(personId);
        if (person == null)
            throw new SomeReasonableUserException("What are you thinking about ???");
        person.setPhoneNumber(phoneNumber);
        dataSource.updatePerson(person);
    }
    

    appContext または dataSource が初期化されていない場合、未処理のランタイム NullPointerException は現在のスレッドを強制終了し、 Thread.defaultUncaughtExceptionHandlerによって処理されます (お気に入りのロガーまたはその他の通知メカニズムを定義して使用するため)。設定されていない場合、ThreadGroup#uncaughtExceptionはスタック トレースをシステム エラーに出力します。アプリケーション エラー ログを監視し、実際にはアプリケーション エラーである未処理の例外ごとに Jira 課題を開く必要があります。プログラマーは、初期化のどこかでバグを修正する必要があります。

于 2011-11-21T12:58:18.847 に答える
71

Java 7java.util.Objectsには、メソッドがある新しいユーティリティ クラスがありrequireNonNull()ます。これは、引数が null の場合に a をスローするNullPointerExceptionだけですが、コードが少しクリーンアップされます。例:

Objects.requireNonNull(someObject);
someObject.doCalc();

このメソッドは、コンストラクターで代入の直前にチェックするのに最も役立ちます。このメソッドを使用するたびに、3 行のコードを節約できます。

Parent(Child child) {
   if (child == null) {
      throw new NullPointerException("child");
   }
   this.child = child;
}

になる

Parent(Child child) {
   this.child = Objects.requireNonNull(child, "child");
}
于 2012-08-10T07:08:00.533 に答える
52

最終的に、この問題を完全に解決する唯一の方法は、別のプログラミング言語を使用することです。

  • Objective-C では、 でメソッドを呼び出すのと同じことを行うことができますが、nilまったく何も起こりません。これにより、ほとんどの null チェックが不要になりますが、エラーの診断がはるかに難しくなる可能性があります。
  • Java 派生言語であるNiceでは、すべての型に 2 つのバージョンがあります。潜在的に null のバージョンと非 null のバージョンです。null 以外の型でのみメソッドを呼び出すことができます。null の可能性がある型は、null を明示的にチェックすることで非 null 型に変換できます。これにより、null チェックが必要な場所と不要な場所を簡単に知ることができます。
于 2009-07-29T20:52:38.367 に答える
38

その質問をすると、エラー処理戦略に興味があるかもしれないことがわかります。エラーを処理する方法と場所は、アーキテクチャ上の広範な問題です。これを行うにはいくつかの方法があります。

私のお気に入り: 例外が波及するのを許可します - 「メインループ」または適切な責任を持つ他の関数で例外をキャッチします。エラー状態をチェックして適切に処理することは、専門的な責任と見なすことができます。

Aspect Oriented Programming もぜひご覧if( o == null ) handleNull()ください。バイトコードに挿入するための優れた方法があります。

于 2008-11-07T09:27:17.813 に答える
37

の使用に加えてassert、以下を使用できます。

if (someobject == null) {
    // Handle null here then move on.
}

これは、次のものよりわずかに優れています。

if (someobject != null) {
    .....
    .....



    .....
}
于 2010-08-17T03:59:45.513 に答える
36

null を使用しないでください。許可しないでください。

私のクラスでは、ほとんどのフィールドとローカル変数に null 以外のデフォルト値があり、コードのいたるところにコントラクト ステートメント (常時オンのアサート) を追加して、これが強制されていることを確認します (それを許可するよりも簡潔で表現力があるため)。 NPE として表示され、回線番号を解決する必要があるなど)。

この慣行を採用すると、問題が自然に解決するように見えることに気付きました. 開発プロセスの早い段階でたまたま何かを見つけて、弱点があることに気付くでしょう..さらに重要なことに..それは、さまざまなモジュールの懸念をカプセル化するのに役立ち、さまざまなモジュールが互いに「信頼」できるようになり、コンストラクトを使ったコードif = null else

これは防御的なプログラミングであり、長い目で見ればはるかにクリーンなコードになります。ここでは、厳格な基準を適用するなどして、常にデータをサニタイズしてください。そうすれば、問題は解決します。

class C {
    private final MyType mustBeSet;
    public C(MyType mything) {
       mustBeSet=Contract.notNull(mything);
    }
   private String name = "<unknown>";
   public void setName(String s) {
      name = Contract.notNull(s);
   }
}


class Contract {
    public static <T> T notNull(T t) { if (t == null) { throw new ContractException("argument must be non-null"); return t; }
}

コントラクトは、本番環境でも常に実行されているミニユニット テストのようなものであり、何かが失敗した場合、ランダムな NPE ではなく、何らかの方法で把握する必要があるため、その理由がわかります。

于 2012-10-18T03:42:36.160 に答える
31

Google の非常に便利なコア ライブラリである Guava には、null を回避するための優れた便利な API があります。UsingAndAvoidingNullExplained はとても役に立ちます。

ウィキで説明されているように:

Optional<T>null 許容の T 参照を null 以外の値に置き換える方法です。Optional には、null 以外の T 参照が含まれるか (この場合、参照は「存在する」といいます)、何も含まれない場合があります (この場合、参照は「存在しない」といいます)。「null を含む」とは決して言われません。

使用法:

Optional<Integer> possible = Optional.of(5);
possible.isPresent(); // returns true
possible.get(); // returns 5
于 2012-03-23T20:16:39.240 に答える
27

これは、すべての Java 開発者にとって非常に一般的な問題です。そのため、Java 8 では、コードを乱雑にすることなくこれらの問題に対処するための公式サポートが用意されています。

Java 8 が導入されましjava.util.Optional<T>た。これは、null 以外の値を保持する場合と保持しない場合があるコンテナーです。Java 8 では、場合によっては値が null になる可能性があるオブジェクトをより安全に処理する方法が提供されています。HaskellScalaのアイデアから着想を得ています。

簡単に言うと、Optional クラスには、値が存在する場合と存在しない場合を明示的に処理するメソッドが含まれています。ただし、null 参照と比較した場合の利点は、Optional<T> クラスを使用すると、値が存在しない場合について考える必要があることです。結果として、意図しないヌル ポインター例外を防ぐことができます。

上記の例では、家庭で利用可能な複数の電化製品へのハンドルを返すホーム サービス ファクトリがあります。ただし、これらのサービスが利用可能/機能している場合とそうでない場合があります。これは、NullPointerException が発生する可能性があることを意味します。サービスを使用する前にnull 条件を追加する代わりに、ifそれを Optional<Service> にラップしましょう。

OPTION<T> へのラップ

ファクトリからサービスの参照を取得する方法を考えてみましょう。サービス参照を返す代わりに、Optional でラップします。これにより、API ユーザーは、返されたサービスが利用可能/機能的である場合とそうでない場合があり、防御的に使用されることを知ることができます。

public Optional<Service> getRefrigertorControl() {
      Service s = new  RefrigeratorService();
       //...
      return Optional.ofNullable(s);
   }

ご覧のとおりOptional.ofNullable()、参照をラップする簡単な方法を提供します。Optional の参照を取得するには、Optional.empty()&のいずれかの別の方法がありますOptional.of()。1 つは null を返す代わりに空のオブジェクトを返すためのもので、もう 1 つは null 非許容オブジェクトをラップするためのものです。

では、NULL チェックを回避するのにどのように役立つのでしょうか?

参照オブジェクトをラップすると、Optional は、NPE を使用せずにラップされた参照でメソッドを呼び出すための多くの便利なメソッドを提供します。

Optional ref = homeServices.getRefrigertorControl();
ref.ifPresent(HomeServices::switchItOn);

Optional.ifPresent は、指定された Consumer が null 以外の値である場合、参照を使用して呼び出します。それ以外の場合は、何もしません。

@FunctionalInterface
public interface Consumer<T>

単一の入力引数を受け入れ、結果を返さない操作を表します。他のほとんどの機能的インターフェースとは異なり、 Consumer は副作用を介して動作することが期待されています。とてもきれいでわかりやすいです。上記のコード例でHomeService.switchOn(Service)は、オプションの保持参照が null でない場合に呼び出されます。

null 条件をチェックするために三項演算子を頻繁に使用し、代替値またはデフォルト値を返します。Optional は、null をチェックせずに同じ条件を処理する別の方法を提供します。Optional.orElse(defaultObj) は、Optional に null 値がある場合、defaultObj を返します。これをサンプル コードで使用してみましょう。

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

現在 HomeServices.get() は同じことを行いますが、より良い方法です。サービスがすでに初期化されているかどうかを確認します。その場合は、同じものを返すか、新しい新しいサービスを作成します。Optional<T>.orElse(T) は、デフォルト値を返すのに役立ちます。

最後に、NPE と null チェックのないコードを次に示します。

import java.util.Optional;
public class HomeServices {
    private static final int NOW = 0;
    private static Optional<HomeServices> service;

public static Optional<HomeServices> get() {
    service = Optional.of(service.orElse(new HomeServices()));
    return service;
}

public Optional<Service> getRefrigertorControl() {
    Service s = new  RefrigeratorService();
    //...
    return Optional.ofNullable(s);
}

public static void main(String[] args) {
    /* Get Home Services handle */
    Optional<HomeServices> homeServices = HomeServices.get();
    if(homeServices != null) {
        Optional<Service> refrigertorControl = homeServices.get().getRefrigertorControl();
        refrigertorControl.ifPresent(HomeServices::switchItOn);
    }
}

public static void switchItOn(Service s){
         //...
    }
}

完全な投稿はNPEであり、Nullチェックのないコードです...本当に?.

于 2015-04-27T04:16:49.873 に答える
24

ナット・プライスの記事が好きです。リンクは次のとおりです。

記事には、Java Maybe TypeのGitリポジトリへのリンクもあります。これは興味深いと思いますが、それだけでチェックコードの膨張を減らすことはできないと思います。インターネットで調査した結果、 != nullコードの膨張は、主に注意深い設計によって減らすことができると思います。

于 2011-08-21T18:33:43.130 に答える
22

私は試してみましたNullObjectPatternが、私にとっては常に最善の方法ではありません。「アクションなし」が適切でない場合もあります。

NullPointerExceptionランタイム例外であり、開発者の責任であり、十分な経験があれば、エラーの場所が正確にわかります。

今答えに:

すべての属性とそのアクセサーをできるだけ非公開にするか、クライアントにまったく公開しないようにしてください。もちろん、コンストラクターで引数値を使用できますが、スコープを縮小することで、クライアント クラスが無効な値を渡さないようにすることができます。値を変更する必要がある場合は、いつでも新しい を作成できますobject。コンストラクターで値を1 回だけチェックすると、残りのメソッドでは、値が null でないことをほぼ確実に確認できます。

もちろん、経験はこの提案を理解し適用するためのより良い方法です。

バイト!

于 2008-11-13T22:08:04.167 に答える
17

もっと一般的に答えてもいいですか!

通常、メソッドが予期しない方法でパラメーターを取得すると、この問題に直面します (不適切なメソッド呼び出しはプログラマーの責任です) 。例: オブジェクトを取得することを期待しているのに、null を取得します。少なくとも 1 文字の文字列を取得することを期待していますが、代わりに空の文字列を取得しています ...

したがって、次の違いはありません。

if(object == null){
   //you called my method badly!

}

また

if(str.length() == 0){
   //you called my method badly again!
}

どちらも、他の関数を実行する前に、有効なパラメーターを受け取ったことを確認したいと考えています。

他のいくつかの回答で述べたように、上記の問題を回避するには、Design by contractパターンに従うことができます。http://en.wikipedia.org/wiki/Design_by_contractを参照してください。

このパターンを Java で実装するには、javax.annotation.NotNullなどのコア Java アノテーションを使用するか、 Hibernate Validatorなどのより洗練されたライブラリを使用できます。

単なるサンプル:

getCustomerAccounts(@NotEmpty String customerId,@Size(min = 1) String accountType)

入力パラメーターをチェックする必要なく、メソッドのコア関数を安全に開発できるようになりました。これらは、予期しないパラメーターからメソッドを保護します。

さらに一歩進んで、アプリケーションで有効な pojo のみを作成できるようにすることができます。(Hibernate Validator サイトのサンプル)

public class Car {

   @NotNull
   private String manufacturer;

   @NotNull
   @Size(min = 2, max = 14)
   private String licensePlate;

   @Min(2)
   private int seatCount;

   // ...
}
于 2014-02-12T11:41:36.560 に答える
16
  1. 変数を null に初期化しないでください。
  2. (1) が不可能な場合は、すべてのコレクションと配列を空のコレクション/配列に初期化します。

独自のコードでこれを行うと、!= null チェックを回避できます。

ほとんどの場合、null チェックはコレクションまたは配列のループを保護しているように見えるため、それらを空に初期化するだけで、null チェックは必要ありません。

// Bad
ArrayList<String> lemmings;
String[] names;

void checkLemmings() {
    if (lemmings != null) for(lemming: lemmings) {
        // do something
    }
}



// Good
ArrayList<String> lemmings = new ArrayList<String>();
String[] names = {};

void checkLemmings() {
    for(lemming: lemmings) {
        // do something
    }
}

これにはわずかなオーバーヘッドがありますが、よりクリーンなコードと NullPointerExceptions の減少には価値があります。

于 2013-06-14T13:05:31.063 に答える
15

これは、ほとんどの開発者に発生する最も一般的なエラーです。

これを処理する方法はいくつかあります。

アプローチ 1:

org.apache.commons.lang.Validate //using apache framework

notNull(オブジェクトオブジェクト、文字列メッセージ)

アプローチ 2:

if(someObject!=null){ // simply checking against null
}

アプローチ 3:

@isNull @Nullable  // using annotation based validation

アプローチ 4:

// by writing static method and calling it across whereever we needed to check the validation

static <T> T isNull(someObject e){  
   if(e == null){
      throw new NullPointerException();
   }
   return e;
}
于 2014-04-11T20:14:20.343 に答える
11
public static <T> T ifNull(T toCheck, T ifNull) {
    if (toCheck == null) {
           return ifNull;
    }
    return toCheck;
}
于 2010-10-13T15:14:44.503 に答える
8

FindBugsを使用できます。また、Eclipseプラグインもあります) は、重複した null チェックを (特に) 見つけるのに役立ちますが、防御的なプログラミングを選択する必要がある場合があることに注意してください。役立つかもしれないJava の契約もあります。

于 2011-03-10T22:00:54.277 に答える
7

Java 7クラスが存在するのでjava.util.Objects

しかし、以来、クラスのメソッドをJava 8使用してヌルポインタチェックを行うことができObjects.isNull(var)ます。Objects.nonNull(var)Objects

例えば、

String var1 = null;
Date var2 = null;
Long var3 = null;

if(Objects.isNull(var1) && Objects.isNull(var2) && Objects.isNull(var3))
    System.out.println("All Null");
else if (Objects.nonNull(var1) && Objects.nonNull(var2) && Objects.nonNull(var3))
    System.out.println("All Not Null");
于 2016-11-28T09:29:50.917 に答える
6

この場合、Guava Preconditions が非常に役立つことがわかりました。NPEを理解する唯一の方法は行番号を見つけることであるため、ヌルポインター例外にヌルを残すのは好きではありません。製品版と開発版では行番号が異なる場合があります。

Guava Preconditions を使用して、null パラメーターをチェックし、意味のある例外メッセージを 1 行で定義できます。

例えば、

Preconditions.checkNotNull(paramVal, "Method foo received null paramVal");
于 2014-03-05T22:44:01.493 に答える
6

もう1つの選択肢:

次の単純な関数は、null チェックを非表示にするのに役立ちます (理由はわかりませんが、同じ共通ライブラリの一部として見つかりませんでした)。

public static <T> boolean isNull(T argument) {
    return (argument == null);
}

あなたは今書くことができます

if (!isNull(someobject)) {
    someobject.doCalc();
}

これは、IMO をより適切に表現する方法です!= null

于 2011-10-21T09:02:37.010 に答える
6

配列またはベクターを渡す場合は常に、これらを null ではなく空のものに初期化します。- このようにして、多くの null のチェックを避けることができ、すべて問題ありません:)

public class NonNullThing {

   Vector vectorField = new Vector();

   int[] arrayField = new int[0];

   public NonNullThing() {

      // etc

   }

}
于 2008-11-07T10:43:47.677 に答える
5

Java 8 ではT、ローカル変数/フィールド/メソッド引数/メソッド戻り型が割り当てられnullていない場合 (および をチェックしない場合null) に typeを使用できます。Optional<T>また、可能な場合は type を使用できますnull。次にmap、処理方法と処理方法を使用しT ->ます。flatMapT -> Optional<R>

class SomeService {
    @Inject
    private CompanyDao companyDao;

    // return Optional<String>
    public Optional<String> selectCeoCityByCompanyId0(int companyId) {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity);
    }

    // return String + default value
    public String selectCeoCityByCompanyId1(int companyId) {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity)
                .orElse("UNKNOWN");
    }

    // return String + exception
    public String selectCeoCityByCompanyId2(int companyId) throws NoSuchElementException {
        return companyDao.selectById(companyId)
                .map(Company::getCeo)
                .flatMap(Person::getHomeAddress)
                .flatMap(Address::getCity)
                .orElseThrow(NoSuchElementException::new);
    }
}

interface CompanyDao {
    // real situation: no company for such id -> use Optional<Company> 
    Optional<Company> selectById(int id);
}

class Company {
    // company always has ceo -> use Person 
    Person ceo;
    public Person getCeo() {return ceo;}
}

class Person {
    // person always has name -> use String
    String firstName;
    // person can be without address -> use Optional<Address>
    Optional<Address> homeAddress = Optional.empty();

    public String getFirstName() {return firstName;}   
    public Optional<Address> getHomeAddress() {return homeAddress;}
}

class Address {
    //  address always contains country -> use String
    String country;
    //  city field is optional -> use Optional<String>
    Optional<String> city = Optional.empty();

    String getCountry() {return country;}    
    Optional<String> getCity() {return city;}
}
于 2016-07-05T15:24:21.573 に答える
4

メソッド呼び出しの前にインターセプターを使用できます。それが、アスペクト指向プログラミングが焦点を当てていることです。

M1(Object test) がメソッドで、M2 がメソッド呼び出しの前にアスペクトを適用するメソッドであるとしますM2(Object test2)。その場合test2 != nullは M1 を呼び出し、そうでない場合は別のことを行います。アスペクトを適用するすべてのメソッドで機能します。インスタンス フィールドとコンストラクターにアスペクトを適用する場合は、 AspectJを使用できます。Springは、メソッドの側面にも最適です。

于 2012-12-03T03:15:23.840 に答える
3

OK、これは技術的に何百万回も回答されていますが、これはJavaプログラマーとの終わりのない議論であるため、これを言わなければなりません.

申し訳ありませんが、上記のほとんどすべてに同意しません。Java で null をテストしなければならない理由は、Java プログラマーがメモリの処理方法を知らないからです。

これは、C++ でのプログラミングに長い経験があり、これを行っていないためです。つまり、その必要はありません。また、Java では、ダングリング ポインターにヒットすると、通常の例外が発生することに注意してください。C++ では、この例外は通常キャッチされず、プログラムを終了します。

やりたくない?次に、C/C++ のいくつかの簡単な規則に従います。

物事を簡単にインスタンス化しないでください。「新しい」ものごとに多くの問題が発生する可能性があると考えて、これらの単純なルールに従ってください。

クラスは 3 つの方法でのみメモリにアクセスする必要があります ->

  1. クラスメンバーを「HAVE」することができ、次の規則に従います。

    1. すべての「HAS」メンバーは、コンストラクターで「新規」に作成されます。
    2. 同じクラスの Java のデストラクタまたは同等の close() 関数で /de allocate を閉じますが、他にはありません。

これは、(Java と同じように) 誰が各リソースの所有者または親であるかを念頭に置き、その所有権を尊重する必要があることを意味します。オブジェクトは、それを作成したクラスによってのみ削除されます。また - >

  1. 一部のメンバーは「USED」ですが、所有または「HAVE」ではありません。これは別のクラスで「所有」され、コンストラクターに引数として渡されます。これらは別のクラスによって所有されているため、これを削除したり閉じたりすることは決してありません。親だけができます。

  2. クラス内のメソッドは、内部使用のためにローカル オブジェクトをインスタンス化することもできます。これは決してクラスの外には渡されないか、通常の「has」オブジェクトである必要があります。

最後に、これらすべてが機能するためには、クラスを階層形式にし、サイクルを作成しない、規則正しい設計が必要です。

この設計の下で、かつ上記の規則に従うと、階層設計の子クラスが破棄されたポインタにアクセスする方法はありません。これは、親が子の前に破棄されたことを意味するため、階層的非循環設計では発生しません。許す。

最後に、システムを起動するときは、階層の上から下に構築し、下から上に破棄する必要があることも忘れないでください。どこにも null ポインターが存在することはありません。または、誰かがルールに違反しています。

于 2012-07-13T21:46:16.470 に答える
3

Java 8 には、オブジェクトを考慮してラップする Optional クラスがあり、値が存在する場合、isPresent() は true を返し、get() は値を返します。

http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html

于 2015-12-16T05:54:05.260 に答える
3

Checker Framework (JDK 7 以降) を使用して、null 値を静的にチェックすることもできます。これにより多くの問題が解決される可能性がありますが、現在 OpenJDK AFAIK でのみ機能する追加のツールを実行する必要があります。https://checkerframework.org/

于 2012-03-23T20:31:43.973 に答える
3
public class Null {

public static void main(String[] args) {
    String str1 = null;
    String str2 = "";

    if(isNullOrEmpty(str1))
        System.out.println("First string is null or empty.");
    else
        System.out.println("First string is not null or empty.");

    if(isNullOrEmpty(str2))
        System.out.println("Second string is null or empty.");
    else
        System.out.println("Second string is not null or empty.");
}

public static boolean isNullOrEmpty(String str) {
    if(str != null && !str.isEmpty())
        return false;
    return true;
}
}

出力

str1 is null or empty.
str2 is null or empty.

上記のプログラムでは、2 つの文字列 str1 と str2 があります。str1 には null 値が含まれ、str2 は空の文字列です。

名前が示すように、文字列が null か空かをチェックする関数 isNullOrEmpty() も作成しました。!= null と文字列の isEmpty() メソッドを使用した null チェックを使用してチェックします。

簡単に言えば、文字列が null ではなく、isEmpty() が false を返す場合、それは null でも空でもありません。そうでなければ、そうです。

ただし、文字列に空白文字 (スペース) のみが含まれている場合、上記のプログラムは空を返しません。技術的には、 isEmpty() はスペースが含まれていることを認識し、false を返します。スペースを含む文字列の場合、文字列メソッド trim() を使用して、先頭と末尾のすべての空白文字を削除します。

于 2020-11-09T07:30:09.023 に答える
2

まず、すべての null 条件を実際に削除することはできません。@NotNull@Nullable注釈を使用してそれらを減らすことができます(すでに述べたように)。ただし、これには何らかのフレームワークによる裏付けが必要です。ここで、OValが役に立ちます。

基本的な考え方は、オブジェクト/パラメーター/コンストラクターが常に前提条件を満たす必要があるということです。Nullableなどの多くの前提条件を設定できますNotNull。OVal は、呼び出されたときにオブジェクトが一貫した状態になるように処理します。

OVal は内部的に AspectJ を使用して前提条件を検証していると思います。

@Guarded
public class BusinessObject
{
  public BusinessObject(@NotNull String name)
  {
    this.name = name;
  }

  ...
}

例えば、

// Throws a ConstraintsViolatedException because parameter name is null
BusinessObject bo = new BusinessObject(null);
于 2013-01-10T07:45:59.320 に答える
2

不要なものを避ける方法null-checksは簡単です。

You need to know which variables can be null, and which cannot, and you need to be confident about which category a given variable fall into.

しかし、それは簡単に言えますが、それを達成するのは難しいです。変数がnullconfidentにならないことをどのように確認できるのでしょうか。

これに対する簡単な解決策はありませんが、以下にいくつかのヒントを示します。

  1. きれいなコード。コードの振る舞いを推論できるようにするために最も重要なことは、コードが理解しやすい形で書かれていることです。変数が表すものに基づいて変数に名前を付け、メソッドに名前を付けて、それらが何をするかに基づいて名前を付けSingle responsibility principleます。単一の責任を持ち、これだけを行います)。コードがきれいになると、コードの複数の層/レイヤーにまたがって、それについて推論するのがはるかに簡単になります。乱雑なコードでは、メソッドの機能を理解しようとすると、そもそもなぜメソッドを読んでいるのかを忘れてしまう可能性があります。(ヒント: Robert C. Martin の「Clean Code」を読んでください)SSOLID

  2. 値を返すことは避けてくださいnull。値によってプログラムが正しく機能しなくなる場合はnull、代わりにスローしexceptionます (適切なエラー処理を必ず追加してください)。値を返すnullことが許容される場合は、たとえば、データベースからオブジェクトを取得しようとする場合です。このような場合、値を処理するコードを記述し、nullを返す可能性があるものがあることを耳の後ろに書き留めておいてくださいnullnull返された値は、返されるメソッドの呼び出し元にできるだけ近い場所で処理nullします (呼び出しチェーンに盲目的に戻さないでください)。

  3. 明示的な値をパラメーターとして渡さnullないでください (少なくともクラス間では)。-パラメーターを渡すことnullが唯一の選択肢である場合は、このパラメーターを持たない新しいメソッドを作成することをお勧めします。

  4. 入力内容を検証してください! アプリケーションへの「エントリ ポイント」を特定します。これらは、Web サービス、REST サービス、リモート EJB クラス、コントローラーなどのすべてを実行できます。これらのエントリ ポイントの各メソッドについて、「このパラメーターが null の場合、このメソッドは正しく実行されるか?」と自問してください。答えがノーの場合は、 を追加しValidate.notNull(someParam, "Can't function when someParam is null!");ます。IllegalArgumentException必要なパラメーターが欠落している場合、これは をスローします。エントリポイントでのこのタイプの検証の良い点は、エントリポイントから実行されるコードで、この変数が null になることはないと簡単に想定できることです! また、これが失敗した場合、エントリポイントにあるため、デバッグは、単に取得した場合よりもはるかに簡単になります。NullPointerExceptionこのような失敗が意味することは 1 つだけなので、コードの奥深くで、クライアントが必要なすべての情報を送信していないということです。ほとんどの場合、すべての入力パラメーターを検証する必要があります。多くの値を許可する必要がある場合はnull、インターフェースの設計が不適切であることを示している可能性があります。クライアント。

  5. s を扱うときCollectionは、null ではなく空のものを返してください!

  6. データベースを操作する場合は、not null-constraints を使用してください。そうすれば、データベースから読み取った値を null にすることはできないことがわかり、チェックする必要がなくなります。

  7. コードを構造化し、それに固執します。これを行うことで、コードの動作に関する仮定を立てることができます。たとえば、アプリケーションへのすべての入力が検証された場合、これらの値が null になることはないと仮定できます。

  8. まだ行っていない場合は、コードの自動テストを作成してください。テストを書くことで、自分のコードについて推論できるようになり、コードが想定どおりに動作するという確信も持てるようになります。また、自動化されたテストは、このコードの一部が以前のように機能していないことをすぐに知らせることで、リファクタリング中の失敗からあなたを守ります。

もちろん、まだヌルチェックを行う必要がありますが、最小限に抑えることができます (つまり、念のためにどこでもではなく、ヌル値を取得している可能性があることがわかっている状況です)。 、私は実際には三項演算子を使用することを好みます(ただし、ネストを開始すると、非常に面倒になりますので、注意して使用してください。)

public String nullSafeToString(final Object o) {
    return o != null ? o.toString() : "null";
}
于 2014-01-27T20:54:30.387 に答える
2

JDK から null 値を確認する良い方法があります。これらの問題を解決するためのメソッドが豊富にあるのが Optional.java です。次のような:

    /**
     * Returns an {@code Optional} describing the specified value, if non-null,
     * otherwise returns an empty {@code Optional}.
     *
     * @param <T> the class of the value
     * @param value the possibly-null value to describe
     * @return an {@code Optional} with a present value if the specified value
     * is non-null, otherwise an empty {@code Optional}
     */
    public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);
    }
    /**
     * Return {@code true} if there is a value present, otherwise {@code false}.
     *
     * @return {@code true} if there is a value present, otherwise {@code false}
     */
    public boolean isPresent() {
        return value != null;
    }
    /**
     * If a value is present, invoke the specified consumer with the value,
     * otherwise do nothing.
     *
     * @param consumer block to be executed if a value is present
     * @throws NullPointerException if value is present and {@code consumer} is
     * null
     */
    public void ifPresent(Consumer<? super T> consumer) {
        if (value != null)
            consumer.accept(value);
    }

javar を支援することは本当に、本当に便利です。

于 2020-10-21T02:23:33.447 に答える
1

私はこれが好きです

public void simpleFunc(SomeObject someObject){
    someObject = someObject != null ? someObject : new SomeObject(null);
    someObject.doSomething();
}

もちろん、私の例では、SomeObjectはnullパラメータを適切に処理します。たとえば、そのようなイベントをログに記録し、それ以上何もしません。

于 2012-09-12T14:54:01.960 に答える
1

Java 8 ラムダを使用して、ネストされた null チェックを処理する util メソッドをほぼきれいな方法で定義することができます。

void example() {
    Entry entry = new Entry();
    // This is the same as H-MANs solution 
    Person person = getNullsafe(entry, e -> e.getPerson());    
    // Get object in several steps
    String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName());
    // Call void methods
    doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt());        
}

/** Return result of call to f1 with o1 if it is non-null, otherwise return null. */
public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) {
    if (o1 != null) return f1.apply(o1);
    return null; 
}

public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) {
    return getNullsafe(getNullsafe(o0, f1), f2);
}

public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) {
    return getNullsafe(getNullsafe(o0, f1, f2), f3);
}


/** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */
public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) {
    if (o1 != null) f1.accept(o1);
}

public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) {
    doNullsafe(getNullsafe(o0, f1), f2);
}

public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) {
    doNullsafe(getNullsafe(o0, f1, f2), f3);
}


class Entry {
    Person getPerson() { return null; }
}

class Person {
    Name getName() { return null; }
}

class Name {
    void nameIt() {}
    String getGivenName() { return null; }
}

(この回答は最初にここに投稿されました。)

于 2015-11-17T17:37:37.150 に答える
1

この問題には Apache ライブラリ (Apache Commons) を使用しています。

ObjectUtils.equals(object, null)

また

CollectionUtils.isEmpty(myCollection);

また

StringUtils.isEmpty("string");

練習として、必要性を最小限に抑えるためにコレクションに初期デフォルト値または空のセットを提供する前の前の回答が好きです。

これらは、NullPointerException が発生したり、空のコレクションを使用したりしないようにする単純な使用方法です。これは、null オブジェクトをどうするかという質問には答えませんが、オブジェクトまたはコレクションの基本的な検証のためのいくつかのチェックを提供します。

お役に立てれば。

于 2013-10-31T19:18:24.977 に答える
0

JUnit などのフレームワークを使用して、クラスをユニット テストと結合できます。このようにして、コードがきれいになり (無駄なチェックがなくなり)、インスタンスが null にならないようになります。

これは、単体テストを使用する (多くの) 正当な理由の 1 つです。

于 2015-10-19T14:00:36.850 に答える
0

ユーティリティ クラスの場合、パラメーターが null でないことを確認できます。

それ以外の場合は、必要ない場合があります。可能な限りカプセル化を使用して、null をチェックしたくなる場所を減らします。

于 2010-05-20T13:16:47.257 に答える
-1

この問題の解決策として、Null オブジェクト パターンを使用できます。そのためには、someObject のクラスを変更する必要があります。

public abstract class SomeObject {
   public abstract boolean isNil();
}

public class NullObject extends SomeObject {
   @Override
   public boolean isNil() {
      return true;
   }
}
public class RealObject extends SomeObject {
   @Override
   public boolean isNil() {
      return false;
   }
}

チェックする代わりに、

 if (someobject != null) {
    someobject.doCalc();
}

私たちは、

if (!someObject.isNil()) {
   someobject.doCalc();
}

参考:https ://www.tutorialspoint.com/design_pattern/null_object_pattern.htm

于 2016-10-04T08:57:46.360 に答える
-5

Another suggestion is to program defensively - where your classes/functions provide default values that are known and safe, and where null is reserved for true errors/exceptions.

For example, instead of functions that return Strings returning null when there is a problem (say converting a number to a string), have them return an empty String (""). You still have to test the return value before proceeding, but there would be no special cases for exceptions. An additional benefit of this style of programming is that your program will be able to differentiate and respond accordingly between normal operations and exceptions.

于 2011-02-16T23:14:35.617 に答える