Существует ли основная реализация Набора Java, которая не разрешает, аннулирует?

System.Guid - это структура, которая не может быть нулевой, поскольку она не является ссылочным типом. Я полагаю, что для известных struct типов, которые реализуют пользовательский оператор равенства (например, int, Guid и т. Д.), Компилятор заменит нулевое сравнение на false. (Следовательно, все операторы сравнения и выброса исчезнут)

Для типов struct, в которых не реализован пользовательский оператор равенства, код просто не будет компилироваться.

Тем не менее, это не нужно.

См: https://sharplab.io/#v2:EYLgtghgzgLgpgJwDQxASwDYB8ACAGAAhwEYBuAWACgcBmIgJgIGECBvKgzounAFgICyACgDiAVzQATAgHMJkgJRsOXVWgBmBIXKkEAvHoIA7MRgxKYACwQB7AO7G4DgIII5YOEZgA5UxgCiAB4AxnAADjBoNkZCChSUqgC+VIlAA===

public void M(Guid guid)
{
    if (guid == null) throw new ArgumentNullException();
}

будет составлен, чтобы:

// Methods
    .method public hidebysig 
        instance void M (
            valuetype [mscorlib]System.Guid guid
        ) cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 1 (0x1)
        .maxstack 8

        IL_0000: ret
    } // end of method C::M

[1110 ] Как видите, первой инструкцией в методе является return.

27
задан Hash 23 March 2017 в 11:56
поделиться

9 ответов

Лучше, чем расширение конкретной реализации, можно легко записать реализацию прокси Set, который проверяет на null с. Это аналогичное Collections.checkedSet. Кроме того, чтобы быть применимым к любой реализации, можно также быть уверены, что Вы переопределили все применимые методы. Много дефектов были найдены путем расширения конкретных наборов, которым тогда добавили дополнительные методы в более поздних версиях.

27
ответ дан Tom Hawtin - tackline 28 November 2019 в 04:40
поделиться

Почему Вы не хотите позволять null?

Вы хотите выдать исключение, если null добавляется к Вашему набору? Если так, просто сделайте что-то вроде этого:

private Set<Object> mySet = new HashSet<Object>() {
    @Override
    public boolean add(Object e) {
        if (e == null)
            throw new IllegalArgumentException("null"); // or NPE
        // or, of course, you could just return false
        return super.add(e);
    }
};

HashSet addAll() вызовы add() неоднократно, таким образом, это - единственный метод, необходимо было бы переопределить.

-1
ответ дан Michael Myers 28 November 2019 в 04:40
поделиться

Я не уверен в типе, который это верно. Но разве Вы не могли наследоваться набору или HashTable по Вашему выбору и переопределить Добавить метод, выдав исключение, если элемент является пустым?

0
ответ дан REA_ANDREW 28 November 2019 в 04:40
поделиться

Можно также хотеть проверить Google Collections . Они - больше страдающего фобией пустого указателя, я верю.

1
ответ дан Julien Chastang 28 November 2019 в 04:40
поделиться

Это - failry способ общего назначения сделать его - Вы обеспечиваете реализацию Фильтра, которая может ограничить то, что добавляется whatevber способом, которым Вы хотите. Смотрите на источник для java.util. Наборы для идей об обертывании (я думаю свой implementaiton класса FilteredCollection, корректны..., но это не протестированный extensivly). Существует пример программы в конце, который показывает использование.

public interface Filter<T>
{
    boolean accept(T item);
}

import java.io.Serializable;
import java.util.Collection;
import java.util.Iterator;


public class FilteredCollections
{
    private FilteredCollections()
    {
    }

    public static <T> Collection<T> filteredCollection(final Collection<T> c,
                                                       final Filter<T>     filter)
    {
        return (new FilteredCollection<T>(c, filter));
    }

    private static class FilteredCollection<E>
        implements Collection<E>,
                   Serializable
    {
        private final Collection<E> wrapped;
        private final Filter<E> filter;

        FilteredCollection(final Collection<E> collection, final Filter<E> f)
        {
            if(collection == null)
            {
                throw new IllegalArgumentException("collection cannot be null");
            }

            if(f == null)
            {
                throw new IllegalArgumentException("f cannot be null");
            }

            wrapped = collection;
            filter  = f;
        }

        public int size()
        {
            return (wrapped.size());
        }

        public boolean isEmpty()
        {
            return (wrapped.isEmpty());
        }

        public boolean contains(final Object o)
        {
            return (wrapped.contains(o));
        }

        public Iterator<E> iterator()
        {
            return new Iterator<E>()
            {
                final Iterator<? extends E> i = wrapped.iterator();

                public boolean hasNext()
                {
                    return (i.hasNext());
                }

                public E next()
                {
                    return (i.next());
                }

                public void remove()
                {
                    i.remove();
                }
            };
        }

        public Object[] toArray() 
        {
            return (wrapped.toArray());
        }

        public <T> T[] toArray(final T[] a)
        {
            return (wrapped.toArray(a));
        }

        public boolean add(final E e)
        {
            final boolean ret;

            if(filter.accept(e))
            {
                ret = wrapped.add(e);
            }
            else
            {
                // you could throw an exception instead if you want - 
               // IllegalArgumentException is what I would suggest
                ret = false;
            }

            return (ret);
        }

        public boolean remove(final Object o)
        {
            return (wrapped.remove(o));
        }

        public boolean containsAll(final Collection<?> c)
        {
            return (wrapped.containsAll(c));
        }

        public boolean addAll(final Collection<? extends E> c)
        {
            final E[] a;
            boolean   result;

            a = (E[])wrapped.toArray();

            result = false;

            for(final E e : a)
            {
                result |= wrapped.add(e);
            }

            return result;
        }

        public boolean removeAll(final Collection<?> c)
        {
            return (wrapped.removeAll(c));
        }

        public boolean retainAll(final Collection<?> c)
        {
            return (wrapped.retainAll(c));
        }

        public void clear() 
        {
            wrapped.clear();
        }

        public String toString()
        {
            return (wrapped.toString());
        }
    }
}


import java.util.ArrayList;
import java.util.Collection;


public class Main
{
    private static class NullFilter<T>
        implements Filter<T>
    {
        public boolean accept(final T item)
        {
            return (item != null);
        }
    }

    public static void main(final String[] argv) 
    {
        final Collection<String> strings;

        strings = FilteredCollections.filteredCollection(new ArrayList<String>(), 
                                                         new NullFilter<String>());
        strings.add("hello");
        strings.add(null);
        strings.add("world");

        if(strings.size() != 2)
        {
            System.err.println("ERROR: strings.size() == " + strings.size());
        }

        System.out.println(strings);
    }
}
2
ответ дан TofuBeer 28 November 2019 в 04:40
поделиться

Вы могли использовать апачские наборы и класс PredicatedCollection, и установить предикат для не разрешения, аннулирует. Вы получите исключения, если кто-то отправит, аннулирует в.

2
ответ дан Uri 28 November 2019 в 04:40
поделиться

Я сказал бы, что состав использования вместо наследования..., это могло бы быть больше работы, но это будет более стабильно перед лицом любых изменений, которые Sun мог бы внести в Платформу Наборов.

public class NoNullSet<E> implements Set<E>
{
   /** The set that is wrapped. */
   final private Set<E> wrappedSet = new HashSet<E>();

   public boolean add(E e)
   {
     if (e == null) 
       throw new IllegalArgumentException("You cannot add null to a NoNullSet");
     return wrappedSet.add(e);
   }

   public boolean addAll(Collection<? extends E> c)
   {
     for (E e : c) add(e);
   }

   public void clear()
   { wrappedSet.clear(); }

   public boolean contains(Object o)
   { return wrappedSet.contains(o); }

   ... wrap the rest of them ...
}

Примечание, что эта реализация не зависит от addAll вызов add (который является деталью реализации и не должен использоваться, потому что это, как могут гарантировать, не останется верным во всех выпусках Java).

22
ответ дан Jens Bannmann 28 November 2019 в 04:40
поделиться

Вы могли легко записать свое собственное путем разделения на подклассы соответствующего существующего класса и переопределения всех соответствующих методов так, чтобы Вы не могли добавлять null элементы.

2
ответ дан mipadi 28 November 2019 в 04:40
поделиться

Кстати, если бы вы попросили реализацию Map , которая не допускает нулей, старая java.util.Hashtable не поддерживает.

0
ответ дан 28 November 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: