- ベストアンサー
GOF本のデザインパターンのCompositeパターンのJava版を実際に動かしてみる際のNullPointerExceptionの理由を教えてください
- GOF本のデザインパターンのCompositeパターンのJava版を実際に動かしてみる際、NullPointerExceptionが発生してしまいます。Equipmentクラス変数としてchassisのオブジェクトがequipmentに渡っているはずなのですが、理由が分かりません。
- CompositeEquipmentクラスの_equipmentはVector型の変数で、addメソッドが呼び出されると_equipmentにequipmentが追加されるはずですが、なぜNullPointerExceptionが発生するのでしょうか。
- NullPointerExceptionの原因として考えられるのは、_equipmentが初期化されていないためです。コード上ではCompositeEquipmentクラスで_equipmentが初期化されていないため、addメソッドが実行されるとNullPointerExceptionが発生します。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
return new NullEnumeration(); で、NullEnumerationクラスが未定義となっています。 また直接的な関係はありませんが、 Bruce Eckel, "Thinking in Java (4th Edition)" (Prentice Hall, 2006) に、 「Vectorの使用は避けよ」 とあります。 http://okwave.jp/qa/q5918977.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); // ... } // ... }
その他の回答 (3)
- erichgumma
- ベストアンサー率48% (13/27)
(補足1) 変数名は、Sun の Naming Convention に従うべきです。 http://www.oracle.com/technetwork/java/codeconventions-135099.html 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-arraylist-vs-vector.html 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
- yamada_g
- ベストアンサー率68% (258/374)
考え方が逆ですね。 NullPointerExceptionはNullのオブジェクトを参照(メソッドの実行やフィールドへのアクセス)しようとした場合に発生します。 なので、このときに引数の equipment ではなく、まずは _equipment に着目するべきです。 解決方法はNo.2さんのおっしゃるとおり _equipment をインスタンス化すればいいです。 また、No.1さんのおっしゃるとおりに、なにか特別な事情がないのであればVectorではなくListを使った方がいいと思います。
お礼
おっしゃる通りです。 Java.utilのコレクション・フレームワークがまだ十分に使いこなせていないのが原因です。 ありがとうございました。
- sakaaja6982
- ベストアンサー率40% (12/30)
_equipmentフィールドをnewしてないように見えます。 CompositeEquipmentのコンストラクタあたりに _equipment = new Vector(); を追加すればいけるでしょうか?
お礼
Vectorのものはこれで解決しました。 ありがとうございました。
お礼
List形式のものでもうまく動作するようになりました。 丁寧なご指摘、ありがとうございました。