 |
|
| 前のページ 1 2 3 4 次のページ |
 |
| インスタンス変数 |
インスタンス変数は決められた場所以外からアクセスできるようになっていると、プログラマのミスや勘違いでインスタンス変数に誤った値などをセットしてしまいバグにつながる可能性があります。インスタンス変数はアクセス権を意識して宣言するようにしましょう。
|
| インスタンス変数初期化のタイミングは「コンストラクタ」または、「インスタンス変数宣言時」または、「初めて値がgetされるタイミング(LazyInitialization)」のいずれかにせよ(C_IVL001) |
インスタンス変数の初期化のタイミングは、「コンストラクタ」「インスタンス変数宣言時」「初めて値がgetされるタイミング」という3通りが考えられます。それぞれのメリット・デメリットを下記に示します。
コンストラクタで初期化の場合
|
public class Product { ⁄** 製品コード *⁄ private String productCode;
⁄** 輸入製品フラグ(輸入製品ならtrue) *⁄ private boolean isImported;
public Product(String productCode) { super(); this.productCode = productCode; isImported = isImported(productCode); } } |
 |
- メリット
- コンストラクタの実行コードはスレッドセーフ(注)なので、マルチスレッド環境下でも面倒な同期処理を考えなくてよい
- コンストラクタにはロジックが書けるので、インスタンスごとに異なる値で初期化することができる(サンプルでは、コンストラクタ内部で製品コードから輸入製品かどうかを判定して輸入製品フラグを初期化している)
- デメリット
- 変数の宣言と初期化が離れたところで行われるので、初期化をうっかり忘れる可能性がある
表1:コンストラクタで初期化のメリット・デメリット
※注:スレッドセーフとは、マルチスレッド環境化で実行されても内部データへのアクセスが競合せずに、常に内部データの整合性が保たれているように対策されている状態のこと。
インスタンス変数宣言時で初期化の場合
|
public class Product { ⁄** 製品を構成する部品のリスト*⁄ private List partsList = new ArrayList(); } |
 |
- メリット
- インスタンス変数宣言部分のコードはスレッドセーフなので、マルチスレッド環境下でも面倒な同期処理を考えなくてよい
- 変数の宣言と初期化が同じステートメント行で行われるので、初期化をうっかり忘れる可能性が少ない
- デメリット
- 複雑なロジックが書けないのでインスタンスごとに初期化できない
表2:インスタンス変数宣言時で初期化のメリット・デメリット
初めて値がgetされるタイミングで初期化の場合
|
public class Product { ⁄** 製品デバッグ情報インスタンス *⁄ private DebugInfo debugInfo;
public DebugInfo getDebugInfo() { if (debugInfo == null) { debugInfo = new ProductDebugInfo(this); } return debugInfo; } } |
 |
- メリット
- サブクラスを定義した時、getメソッドのオーバライドにより初期化操作もオーバライドできる
- 値をgetする際、getメソッドを呼び出す側でのnullチェックの必要がない(通常getメソッド内でチェックするため)
- 滅多に利用されないインスタンス変数や初期化処理に時間がかかるものをインスタンス変数の利用時に行うことでメモリを節約できると同時に、インスタンス初期化の実行時間を速くできる
- デメリット
- 複数のスレッドから同時にgetメソッドが呼ばれる場合、不整合が起こり得る
- 同一クラス内であっても、常にgetメソッドを使ってアクセスしなければならない(インスタンス変数に直接アクセスすると初期化されていない可能性があるため)
- getメソッドのロジックに初期化処理が含まれるため実装が複雑になる
- 変数の宣言と初期化が離れたところで行われるので、初期化をうっかり忘れる可能性がある
表3:初めて値がgetされるタイミングで初期化のメリット・デメリット
|
以上のように、インスタンス変数を初期化する3つの方法には、それぞれメリットとデメリットがあります。
使い分けの指針としては、インスタンス変数宣言と同時に初期化を行うことを基本にして、少々複雑な初期化が必要なインスタンス変数やインスタンスごとに値を変えなければならないものはコンストラクタで初期化を行い、滅多に利用されないインスタンス変数や初期化処理に時間がかかるものはgetメソッドで初期化を行うとよいでしょう。
|
| インスタンス変数はprivateにする(C_IVL002) |
インスタンス変数をpublicまたはデフォルト(package-private)にしてしまうと、そのインスタンス変数を他のクラスが直接アクセスできるようになるため、他のクラスが誤った値をセットして、そのインスタンスの内部状態を壊してしまうなどのトラブルが発生してしまいます。
しかし、インスタンス変数のアクセス修飾子をprivateにすることで、外部のクラスによるインスタンス変数の変更は、setメソッドによる値のセットに一本化されます。setメソッドの中では、不正な値がセットされようとしていないかをチェックするロジックを記述することも可能ですので、外部のクラスによって誤った値がセットされたとしてもエラーとして検出され、インスタンスの内部状態を常に正しく保つことができます。
|
前のページ 1 2 3 4 次のページ
|

|
 |

| 著者プロフィール 株式会社電通国際情報サービス 高安 厚思 株式会社電通国際情報サービス 開発技術センター Java(J2EE)/オブジェクト指向の研究開発やプロジェクト支援、開発コンサルティングに従事。モデル、アーキテクチャ、プロセスが探求対象。今回は Javaコーディング規約2004の仕掛け人。
| 
| 著者プロフィール 株式会社電通国際情報サービス 東田 健宏 株式会社電通国際情報サービス 開発技術センター CTI、Webアプリの開発経験を経て、現在は主にプロジェクトマネジメント支援、プロセスエンジニアリング、ソフトウェア工学研究開発に従事。最近はコーチング、ファシリテーションといったヒューマン系スキルに興味を持ち日々修得に努めている。
| 
| 著者プロフィール 株式会社電通国際情報サービス 藤村 浩士 株式会社電通国際情報サービス アウトソーシング事業部所属 Java(J2EE)に関わる研究開発やプロジェクト支援の経験を経て、現在は、大手企業の業務会計システムの開発プロジェクトに従事。開発の傍らで、プロジェクトの「見える化」にも関心があり、オープンソースを組み合わせて「見える化」の実現に勤しんでいる。
|
|
 |
|
 |
|