Is there a standard Java List implementation that doesn't allow adding null to it?

我只是一个虾纸丫 提交于 2019-12-29 04:30:10

问题


Say I have a List and I know that I never want to add null to it. If I am adding null to it, it means I'm making a mistake. So every time I would otherwise call list.add(item) I would instead call if (item == null) throw SomeException(); else list.add(item);. Is there an existing List class (maybe in Apache Commons or something) that does this for me?

Similar question: Helper to remove null references in a Java List? but I don't want to remove all the nulls, I want to make sure they never get added in the first place.


回答1:


Watch out -- several answers here are claiming to solve your problem by wrapping a list and checking in add and addAll, but they're forgetting you can also add to a List via its listIterator. It's challenging to get a constrained list right, which is why Guava has Constraints.constrainedList to do it for you.

But before looking at that, first consider whether you only need an immutable list, in which case Guava's ImmutableList will do that null checking for you anyway. And in the off chance that you can use one of the JDK's Queue implementations instead, that'll do it too.

(Good list of null-hostile collections: https://github.com/google/guava/wiki/LivingWithNullHostileCollections)




回答2:


Use Apache Commons Collection:

ListUtils.predicatedList(new ArrayList(), PredicateUtils.notNullPredicate());

Adding null to this list throws IllegalArgumentException. Furthermore you can back it by any List implementation you like and if necessary you can add more Predicates to be checked.

Same exists for Collections in general.

Use Google Guava:

Constraints.constrainedList(new ArrayList(), Constraints.notNull())

Adding null to this list throws NullPointerException.




回答3:


AFAIK, there is no standard implementation available in the JDK. However, the Collection spec says that NullPointerException should be thrown when a collection does not support nulls. you can use the following wrapper to add the functionality to any Collection (you'll have to implement the other Collection methods to delegate them to the wrapped instance):

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);
    }
    ...
}



回答4:


You might do this by just wrapping an instance of a List and providing the null-checked add method. In other words, your class would just have a couple of methods and in inner variable.

If you need the full functionality of a list, you might consider Guava's (used to be Google Collections) ForwardingList.

Another approach is to just extend List, but the gotcha there is that you need to override both add and addAll.

Interestingly, guava has a standardAddAll, which can be used as the implementation of addAll, which solves at least part of the problem.




回答5:


Although this problem sort of yells "delegate", it's much easier with subclassing since you intend to inherit almost all the same functionality.

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);
  }
}



回答6:


This should work

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);
}

however a bug in the addAll implementation means you need to use the following

List<String> list = Collections.checkedList(
   Collections.checkedList(new ArrayList<String>(), String.class), String.class);

and you get

list.add(null); threw java.lang.NullPointerException
list.addAll("", null); threw java.lang.NullPointerException



回答7:


try Collections.checkedList().



来源:https://stackoverflow.com/questions/6433478/is-there-a-standard-java-list-implementation-that-doesnt-allow-adding-null-to-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!