Существует ли стандартная реализация Java List, которая не позволяет добавлять к ней нуль?
Скажем, у меня есть List
, и я знаю, что я никогда не хочу добавлять null
к нему. Если я добавляю null к нему, это означает, что я делаю ошибку. Поэтому каждый раз, когда я иначе называл бы list.add(item)
, вместо этого я бы назвал if (item == null) throw SomeException(); else list.add(item);
. Есть ли существующий класс List
(возможно, в Apache Commons или что-то еще), который делает это для меня?
Подобный вопрос: Помощник для удаления нулевых ссылок в списке Java?, но я не хочу удалять все нули, я хочу убедиться, что они никогда не получат добавлено в первую очередь.
Ответы
Ответ 1
Остерегайтесь - несколько ответов здесь требуют решить вашу проблему, обернув список и проверив add
и addAll
, но они забывают, что вы также можете добавить к List
через его listIterator
, Это сложно получить ограниченный список прав, поэтому Guava имеет Constraints.constrainedList
, чтобы сделать это для вас.
Но прежде чем смотреть на это, сначала подумайте, нужен ли вам только непреложный список, и в этом случае Guava ImmutableList
будет выполнять эту нулевую проверку для вас. И в противном случае вы можете использовать одну из реализаций JDK Queue
, и это тоже сделает.
(Хороший список нуль-враждебных коллекций: https://github.com/google/guava/wiki/LivingWithNullHostileCollections)
Ответ 2
Использование коллекции Apache Commons:
ListUtils.predicatedList(new ArrayList(), PredicateUtils.notNullPredicate());
Добавление значения null в этот список вызывает IllegalArgumentException
. Кроме того, вы можете поддержать его с помощью любой реализации списка, которая вам нравится, и при необходимости вы можете добавить дополнительные предикаты для проверки.
То же самое существует для коллекций в целом.
Использовать Google Guava:
Constraints.constrainedList(new ArrayList(), Constraints.notNull())
Добавление значения null в этот список вызывает NullPointerException
.
Ответ 3
AFAIK, стандартная реализация недоступна в JDK. Тем не менее, Спецификация коллекции говорит, что 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);
}
...
}
Ответ 4
Вы можете сделать это, просто обернув экземпляр списка и предоставив метод добавления с нулевым значением. Другими словами, ваш класс будет иметь только несколько методов и во внутренней переменной.
Если вам нужна полная функциональность списка, вы можете рассмотреть Guava (обычно это Google Collections) ForwardingList.
Другой подход состоит в том, чтобы просто расширить List, но в gotcha есть то, что вам нужно переопределить как add
, так и addAll
.
Интересно, что guava имеет standardAddAll, который может использоваться как реализация addAll, который решает хотя бы часть проблемы.
Ответ 5
Хотя эта проблема вызывает крики "делегировать", это намного проще с подклассом, поскольку вы намерены наследовать почти все те же функциональные возможности.
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
попробуйте Collections.checkedList().
Ответ 7
Это должно работать
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