5

私は最近新しいプロジェクトを開始し、インスタンス変数を常に何らかの値に初期化しようとしているので、いつでもnullになることはありません。以下の小さな例:

public class ItemManager {

  ItemMaster itemMaster;
  List<ItemComponentManager> components;

  ItemManager() {
    itemMaster = new ItemMaster();
    components = new ArrayList<ItemComponentManager>();
  }

  ...
}

重要なのは、主に、コードのどこかでインスタンス変数を使用する前に、面倒なnullのチェックを回避することです。これまでのところ、これは正常に機能しており、空の文字列や空のリストなどもチェックできるため、 null値はほとんど必要ありません。スコープが非常に限られているため、メソッドスコープの変数にはこのアプローチを使用していません。コードの他の部分には影響しません。

これはすべて実験的なものなので、このアプローチが機能するかどうか、またはまだ見ていませんがいくつかの落とし穴があるかどうかを知りたいと思います。一般的に、インスタンス変数を初期化しておくのは良い考えですか?

4

12 に答える 12

9

私は通常、空のコレクションとnullコレクションを2つの別個のものとして扱います。

空のコレクションは、利用可能なアイテムがゼロであることを私が知っていることを意味します。nullコレクションは、コレクションの状態がわからないことを教えてくれますが、これは別のことです。

だから私はそれがどちらか/またはだとは本当に思いません。そして、コンストラクターで変数を初期化すると、変数finalを宣言します。最終的に宣言すると、このコレクションをnullにすることはできないことが読者に非常に明確になります。

于 2009-02-13T10:00:16.330 に答える
4

何よりもまず、制御を保持したい場合は、すべての非 final インスタンス変数をプライベートに宣言する必要があります。

遅延インスタンス化も検討してください。これも「悪い状態」を回避しますが、使用時にのみ初期化されます。

class Foo {
    private List<X> stuff;
    public void add(X x) {
        if (stuff == null)
            stuff = new ArrayList<X>();
        stuff.add(x);
    }
    public List<X> getStuff() {
        if (stuff == null)
            return Collections.emptyList();
        return Collections.unmodifiableList(stuff);
    }
}

( Collections.unmodifiableList の使用に注意してください。呼び出し元がリストに追加/削除できるようにしたい場合を除き、不変にする必要があります)

問題のオブジェクトのインスタンスがいくつ作成されるかを考えてみてください。多数のオブジェクトがあり、常にリストを作成する場合 (そして多くの空のリストになる可能性がある場合)、必要以上に多くのオブジェクトを作成する可能性があります。

それ以外は、それは本当に好みの問題であり、構築するときに意味のある値を持つことができるかどうかです.

DI/IOC を使用している場合は、フレームワークで作業を行う必要があります (ただし、コンストラクター インジェクションを介して行うこともできます。私はセッターの方が好みです) -- Scott

于 2009-02-13T12:52:07.053 に答える
3

実際のデータではなく、そこに「空の」プレースホルダー値があることを覚えている限り、それはまったく問題ありません。

それらをnullのままにしておくと、それらに対処しなければならないという利点があります。そうしないと、プログラムがクラッシュします。空のオブジェクトを作成しても、それらを忘れると、未定義の結果が得られます。

そして、防御的なコーディングについてコメントするだけです-あなたがオブジェクトを作成していて、それらをnullに設定したことがない場合は、毎回nullをチェックする必要はありません。何らかの理由でnull値を取得した場合は、何かが壊滅的に間違っていることがわかり、プログラムはとにかくクラッシュするはずです。

于 2009-02-13T09:59:17.143 に答える
2

できれば最終的にします。次に、コンストラクターで初期化する必要があり、nullになることはできません。

また、他のクラスがnullを割り当てないように、どのような場合でもそれらをプライベートにする必要があります。クラスでnullが割り当てられていないことを確認できれば、このアプローチは機能します。

于 2009-02-13T10:09:49.487 に答える
2

これが問題を引き起こすいくつかのケースに出くわしました。逆シリアル化中に、一部のフレームワークはコンストラクターを呼び出しません。どのように、またはなぜこれを行うことを選択したのかはわかりませんが、発生します。これにより、値が になる可能性がありますnull。コンストラクターが呼び出されたが、何らかの理由でメンバー変数が初期化されていない場合にも遭遇しました。

実際には、あなたの代わりに次のコードを使用します。

public class ItemManager {

  ItemMaster itemMaster = new ItemMaster();
  List<ItemComponentManager> components = new ArrayList<ItemComponentManager>();

  ItemManager() {
     ...
  }
  ...
}
于 2009-02-13T10:19:01.760 に答える
2

宣言する変数を処理する方法は、オブジェクト (または静的な場合はクラス) の存続期間中に変数が変更されるかどうかを決定することです。答えが「いいえ」の場合は、最終的なものにします。

最終的にすると、オブジェクトが作成されたときに値を与える必要があります...個人的には、ポイントを変更することを知っていない限り、次のことを行います。

  プライベート 最終 ItemMaster itemMaster;
  プライベート最終リスト コンポーネント。

  // インスタンス初期化ブロック - 構築時に発生
  {
      itemMaster = 新しい ItemMaster();
      コンポーネント = 新しい ArrayList();
  }

現在のコードでは、変数をプライベートとしてマークしていないため、常に null をチェックする必要があります (つまり、同じパッケージ内のどのクラスでも値を null に変更できます)。

于 2009-02-13T17:56:29.367 に答える
1

はい、コンストラクターですべてのクラス変数を初期化することをお勧めします。

于 2009-02-13T09:58:11.140 に答える
1

重要なのは、主に、コードのどこかでクラス変数を使用する前に、面倒なnullのチェックを回避することです。

nullをチェックする必要があります。サードパーティのライブラリやJavaAPIでさえnullを返すことがあります。

また、決して使用されない可能性のあるオブジェクトをインスタンス化することは無駄ですが、それはクラスの設計に依存します。

于 2009-02-13T10:01:22.270 に答える
1

オブジェクトは、構築後に 100% 使用できる状態になっている必要があります。ユーザーが null をチェックする必要はありません。防御的プログラミングが進むべき道です - チェックを続けてください。

DRY のために、セッターにチェックを入れて、コンストラクターにそれらを呼び出させるだけです。そうすれば、チェックを 2 回コーディングする必要がなくなります。

于 2009-02-13T10:45:22.053 に答える
0

いずれかの方法で設定した場合はどうなりますか

itemMaster = null; 

または、ItemManagerへの参照を他のクラスに返し、itemMasterをnullとして設定します。(これにより、ItemManagerなどのクローンが簡単に返されるのを防ぐことができます)

これが可能であるため、私はチェックを続けます。

于 2009-02-13T09:56:54.167 に答える
0

それがすべてあなたのコードであり、その規則を設定したいのであれば、それは良いことです。ただし、誤ったコードがクラス変数の1つを誤ってnullに設定することを防ぐものは何もないというPaulのコメントに同意します。原則として、私は常にnullをチェックします。ええ、それはPITAですが、防御的なコーディングは良いことかもしれません。

于 2009-02-13T09:59:09.250 に答える
0

クラス「ItemManager」の名前から、ItemManagerは一部のアプリではシングルトンのように聞こえます。もしそうなら、あなたは調査し、本当に、本当に、依存性注入を知っているべきです。Spring(http://www.springsource.org/)のようなものを使用して、ItemComponentManagerのリストを作成してItemManagerに挿入します。

DIがなければ、深刻なアプリで手動で初期化することはデバッグにとって悪夢であり、さまざまな「マネージャー」クラスを接続して狭いテストを行うことは地獄です。

常にDIを使用します(テストを作成する場合でも)。データオブジェクトの場合、リストが存在しない場合にリストを作成するget()メソッドを作成します。ただし、オブジェクトが複雑な場合は、ほぼ確実に、ファクトリまたはビルダーパターンを使用して生活を改善し、必要に応じてF/Bにメンバー変数を設定させます。

于 2009-02-13T19:23:13.027 に答える