私がList
を持っていて、null
を追加したくないことを知っているとします。 nullを追加している場合、それは間違いを犯していることを意味します。したがって、そうでなければlist.add(item)
を呼び出すたびに、代わりにif (item == null) throw SomeException(); else list.add(item);
を呼び出します。これを行う既存のList
クラス(Apache Commonsなどにある)はありますか?
同様の質問: Java List? でnull参照を削除するヘルパー)==しかし、すべてのnullを削除するのではなく、追加されないようにしたいそもそも。
注意してください-ここでいくつかの回答は、リストをラップしてadd
とaddAll
をチェックインすることで問題を解決すると主張していますが、List
を介してlistIterator
に追加することもできません。制限されたリストを正しく取得するのは難しいので、GuavaはConstraints.constrainedList
してください。
しかし、それを見る前に、まずimmutableリストだけが必要かどうかを検討してください。この場合、GuavaのImmutableList
はとにかくnullチェックを行います。代わりに、JDKのQueue
実装の1つを代わりに使用できる可能性があれば、それもそれで十分です。
(null-hostileコレクションの良いリスト: https://github.com/google/guava/wiki/LivingWithNullHostileCollections )
Apache Commons Collectionを使用:
ListUtils.predicatedList(new ArrayList(), PredicateUtils.notNullPredicate());
このリストにnullを追加すると、IllegalArgumentException
がスローされます。さらに、好きなList実装でそれをサポートすることができ、必要に応じて、チェックする述語をさらに追加できます。
コレクションについても同様です。
Googleグアバを使用:
Constraints.constrainedList(new ArrayList(), Constraints.notNull())
このリストにnullを追加すると、NullPointerException
がスローされます。
AFAIK、JDKで利用可能な標準実装はありません。ただし、 Collection spec は、コレクションがnullをサポートしていない場合にNullPointerExceptionがスローされることを示しています。次のラッパーを使用して、任意のコレクションに機能を追加できます(ラップされたインスタンスに委任するには、他のコレクションメソッドを実装する必要があります)。
class NonNullCollection<T> implements Collection<T> {
private Collection<T> wrapped;
public NonNullCollection(Collection<T> wrapped) {
this.wrapped = wrapped;
}
@Override
public void add(T item) {
if (item == null) throw new NullPointerException("The collection does not support null values");
else wrapped.add(item);
}
@Override
public void addAll(Collection<T> items) {
if (items.contains(null)) throw new NullPointerException("The collection does not support null values");
else wrapped.addAll(item);
}
...
}
Listのインスタンスをラップし、null-checked addメソッドを提供するだけでこれを行うことができます。言い換えれば、あなたのクラスはいくつかのメソッドと内部変数を持つだけです。
リストのすべての機能が必要な場合は、Guava(以前はGoogleコレクションでした) ForwardingList を検討してください。
もう1つのアプローチは、Listを拡張することですが、add
とaddAll
の両方をオーバーライドする必要があります。
興味深いことに、guavaには standardAddAll があります。これは、問題の少なくとも一部を解決するaddAllの実装として使用できます。
この問題は一種の「委任」を叫びますが、ほとんどすべて同じ機能を継承するつもりであるため、サブクラス化を使用する方がはるかに簡単です。
class MyList extends List {
//Probably need to define the default constructor for the compiler
public add(Object item) {
if (item == null) throw SomeException();
else super.add(item);
}
public addAll(Collection c) {
if (c.contains(null)) throw SomeException();
else super.addAll(c);
}
}
これはうまくいくはずです
List<String> list = Collections.checkedList(new ArrayList<String>(), String.class);
try {
list.add(null);
throw new AssertionError("Expected a NPE");
} catch (NullPointerException expected) {
System.out.println("list.add(null); threw "+expected);
}
try {
List<String> list2 = Arrays.asList("", null);
list.addAll(list2);
throw new AssertionError("Expected a NPE");
} catch (NullPointerException expected) {
System.out.println("list.addAll(\"\", null); threw " + expected);
}
ただし、addAll実装のバグは、以下を使用する必要があることを意味します
List<String> list = Collections.checkedList(
Collections.checkedList(new ArrayList<String>(), String.class), String.class);
そしてあなたは得る
list.add(null); threw Java.lang.NullPointerException
list.addAll("", null); threw Java.lang.NullPointerException