dポイントプレゼントキャンペーン実施中!

GOF本のデザインパターンのCompositeパターンのJava版を実際に動かしてみようと思って、ちょっと手を加えて下記のようなコードにしているのですが、Mainのcabinet.add(chassis);の所で、
CompositeEquipmentクラスの_equipment.addElement(equipment);を呼び出した所で、
何故かNullPointerException例外が発生してしまいます。Equipmentクラス変数としてchassisのオブジェクトがequipmentに渡っているはずなのですが、理由がよく分かりません。どなたか、お分かりになる方、御教示いただけたらと思います。

//ここから
import java.util.Vector;
import java.util.Enumeration;
//Mainクラス
public class Main {
public static void main(String[] args) {
  // TODO 自動生成されたメソッド・スタブ
  Cabinet cabinet = new Cabinet("PC Cabinet");
Chassis chassis = new Chassis("PC Chassis");

cabinet.add(chassis);
       //以下省略

}

}
// Equipmentクラス
abstract class Equipment {
public Equipment(String name) {
_name = name;
}

String name() { return _name; }

  //一部省略

public void add(Equipment equipment) { }
public void remove(Equipment equipment) { }
public Enumeration createEnumeration() {
return new NullEnumeration();
}

private String _name;

}
//CompositeEquipmentクラス
class CompositeEquipment extends Equipment {
public CompositeEquipment(String name) {
super(name);
// ...
}

  //一部省略

public void add(Equipment equipment) {
_equipment.addElement(equipment);
//System.out.println(equipment);
}

public void remove(Equipment equipment) {
_equipment.removeElement(equipment);
}

public Enumeration createEnumeration() {
// concrete iterator を作成する
return new NullEnumeration();
}

private Vector _equipment;
}
//Cabinetクラス
ublic class Cabinet extends CompositeEquipment {
public Cabinet(String name) {
super(name);
// ...
}
// ...

}
//Chassisクラス
public class Chassis extends CompositeEquipment {
public Chassis(String name) {
super(name);
// ...
}
// ...

}
//ここまで

A 回答 (4件)

return new NullEnumeration();



で、NullEnumerationクラスが未定義となっています。


また直接的な関係はありませんが、
Bruce Eckel, "Thinking in Java (4th Edition)" (Prentice Hall, 2006)
に、

「Vectorの使用は避けよ」

とあります。
http://oshiete.goo.ne.jp/qa/5918977.html



import java.util.*;

public class PersonalComputer {
public static void main(String[] args) {

Cabinet cabinet = new Cabinet("PC Cabinet");
Chassis chassis = new Chassis("PC Chassis");

cabinet.add(chassis);
cabinet.remove(chassis);
//以下省略
}
}

// Equipmentクラス
abstract class Equipment {
private String name;
protected Equipment(String name) {
this.name = name;
}

public String getName() {
return name;
}

//一部省略
abstract public void add(Equipment equipment);
abstract public void remove(Equipment equipment);
abstract public Iterator<Equipment> createIterator();
}

//CompositeEquipmentクラス
class CompositeEquipment extends Equipment {
private List<Equipment> equipments = new ArrayList<Equipment>();
protected CompositeEquipment(String name) {
super(name);
// ...
}
//一部省略

public void add(Equipment equipment) {
equipments.add(equipment);
System.out.println(equipment);
}

public void remove(Equipment equipment) {
equipments.remove(equipment);
}

public Iterator<Equipment> createIterator() {
// concrete iterator を作成する
return equipments.iterator();
}
}

//Chassisクラス
class Chassis extends CompositeEquipment {
public Chassis(String name) {
super(name);
// ...
}
// ...
}

//Cabinetクラス
class Cabinet extends CompositeEquipment {
public Cabinet(String name) {
super(name);
// ...
}
// ...
}
    • good
    • 0

(補足1)


変数名は、Sun の Naming Convention に従うべきです。

http://www.oracle.com/technetwork/java/codeconve …

Variables

Variable names should not start with underscore _ or dollar sign $ characters, even though both are allowed.





(補足2)
Vector の使用は、「JVM 1.1 以前の環境を使っている時だけ」に限定すべきです。

http://www.velocityreviews.com/forums/t132806-ar …

John Bollinger:

Choose ArrayList unless you need the code to run in a 1.1 JVM. Period.

All of Vector's methods are synchronized and thus Vector might seem to
be a natural choice for multithreaded scenarios, but that is a trap.
There are a number of fairly routine usage scenarios that require
higher-level synchronization (e.g. iterating through the list), and
programmers who make a blanket assumption that Vector is safe for
multithreaded scenarios run into trouble. If you need to share a List
of some flavor among multiple threads then you must always analyze the
usage and synchronize appropriately. As long as you're going to do that
anyway, Vector doesn't really offer any advantage. You may also be able
to use fewer total monitors for synchronization (e.g. if there are other
shared objects you need to protect as well) with an ArrayList than with
a Vector. Plus, the explicit synchronization that you put in the source
code to protect an ArrayList clues in future maintainers to be thread-aware.





Dale King:

Multithreading is not a valid reason to use Vector since you can do:

List myList = java.util.Collections.synchronizedList(new ArrayList());

Supporting legacy is really the only reason to choose Vector.




Tony Morris:

A java.util.Vector should (speaking from a purist point of view) only be
used if you wish to support VMs prior to 1.2.
The same can be said for java.util.Hashtable.

If you need thread-safety you synchronize your java.util.List using
java.util.Collections.
This is the *nice* way of doing it.

There is no advantage to doing:
java.util.List l = new java.util.Vector();
over
java.util.List
    • good
    • 0
この回答へのお礼

List形式のものでもうまく動作するようになりました。
丁寧なご指摘、ありがとうございました。

お礼日時:2010/08/25 19:51

考え方が逆ですね。


NullPointerExceptionはNullのオブジェクトを参照(メソッドの実行やフィールドへのアクセス)しようとした場合に発生します。
なので、このときに引数の equipment ではなく、まずは _equipment に着目するべきです。
解決方法はNo.2さんのおっしゃるとおり _equipment をインスタンス化すればいいです。
また、No.1さんのおっしゃるとおりに、なにか特別な事情がないのであればVectorではなくListを使った方がいいと思います。
    • good
    • 0
この回答へのお礼

おっしゃる通りです。
Java.utilのコレクション・フレームワークがまだ十分に使いこなせていないのが原因です。
ありがとうございました。

お礼日時:2010/08/25 19:50

_equipmentフィールドをnewしてないように見えます。



CompositeEquipmentのコンストラクタあたりに
_equipment = new Vector();
を追加すればいけるでしょうか?
    • good
    • 0
この回答へのお礼

Vectorのものはこれで解決しました。
ありがとうございました。

お礼日時:2010/08/25 19:46

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!