Zastanawiam się, dlaczego java.util.ArrayList
pozwala to dodać null
. Czy jest jakiś przypadek, w którym chciałbym dodać null
do ArrayList
?
Zadaję to pytanie, ponieważ w projekcie mieliśmy błąd, gdzie niektóre kod został dodając null
do ArrayList
i trudno było dostrzec, gdzie był błąd. Oczywiście NullPointerException
wyrzucono a, ale dopóki inny kod nie próbował uzyskać dostępu do elementu. Problem polegał na tym, jak zlokalizować kod, który dodał null
obiekt. Byłoby łatwiej, gdyby ArrayList
wrzucił wyjątek w kodzie, w którym dodawano elementy.
java
api-design
collections
Alfredo Osorio
źródło
źródło
null
na większość swoich kolekcji).null
jest to domyślny sposób reprezentowania brakujących danych w Javie, czy ci się to podoba, czy nie. W rzeczywistości wielu ludziom się to nie podoba i argumentuje to za funkcjonalnymi rzeczami w stylu programowania. Najbardziej pozytywna odpowiedź nie ma sensu / nie oddaje istoty problemu.null
jest. „Brak” to tylko jedna z kilku potencjalnych interpretacjinull
. Inne prawidłowe interpretacje mogą być „Nieznane”, „Nie dotyczy” lub „Niezainicjowane”. To, conull
reprezentuje, zależy od aplikacji. Jak powiedzieliby społeczność Python: „W obliczu dwuznaczności odmów pokusy zgadywania”. Odmowa trzymania wartości null w pojemniku, który jest w stanie to zrobić, byłaby tylko - zgadnij.Odpowiedzi:
Ta decyzja projektowa wydaje się wynikać głównie z nazewnictwa.
Name ArrayList sugeruje czytelnikowi funkcjonalność podobną do tablic - i jest rzeczą naturalną, że projektanci Java Collections Framework oczekują, że zdecydowana większość użytkowników API będzie polegać na tym, że działa podobnie do tablic.
W szczególności dotyczy to traktowania zerowych elementów. Użytkownik interfejsu API, wiedząc, że poniżej działa OK:
byłby bardzo zaskoczony , aby dowiedzieć się, czy podobny kod ArrayList rzucał NPE:
Rozumowanie jak wyżej przedstawiono w samouczku JCF, podkreślając punkty, które sugerują ścisłe podobieństwo między ArrayList i zwykłymi tablicami:
Jeśli chcesz, aby implementacja listy nie zezwalała na wartości null, lepiej byłoby ją wywołać tak
NonNullableArrayList
lub coś takiego, aby uniknąć mylących użytkowników interfejsu API.Na marginesie znajduje się pomocnicza dyskusja w komentarzach poniżej, wraz z dodatkowymi uwagami na poparcie przedstawionego tutaj rozumowania.
źródło
LinkedList
równieżnull
wpisy listy.null
wpisów jest przydatne w wielu przypadkach.Wartość null może być prawidłową wartością dla elementu listy. Powiedz, że twoja lista zawiera elementy, które reprezentują niektóre opcjonalne dane o liście użytkowników i jest przechowywana w tej samej kolejności, co użytkownicy. Jeśli dodatkowe dane zostaną wypełnione, twoja lista będzie zawierać dodatkowe dane, w przeciwnym razie miejsce odpowiadające użytkownikowi będzie puste. (Jestem pewien, że są lepsze przykłady, ale masz pomysł)
jeśli nie chcesz zezwalać na dodawanie wartości null, możesz owinąć listę tablic własnym opakowaniem, które powstało po dodaniu wartości null.
źródło
ArrayList
zezwala na wartość zerową. To jest celowe. Z javadoc :Odpowiedź na „dlaczego” jest taka, że jeśli nie, ArrayList nie byłby użyteczny w przypadkach, w których konieczne jest umieszczenie
null
listy na liście. W przeciwieństwie do tego, możesz uniemożliwić ArrayListowi zawieranie wartości null, albo testując wartości przed ich dodaniem, albo używając opakowania, które temu zapobiega.Oczywiście każdy przypadek
null
ma wyraźne znaczenie. Na przykład może to oznaczać, że wartość na danym miejscu na liście nie została zainicjowana ani dostarczona.Możesz łatwo zaimplementować to zachowanie, tworząc klasę opakowania. Jednak nie jest to zachowanie, którego potrzebuje większość programistów / aplikacji.
źródło
Czy jest jakiś przypadek, w którym chciałbym dodać wartość null do ArrayList?
Jasne, a co z wstępną alokacją? Chcesz
ArrayList
czegoś, czego nie możesz jeszcze utworzyć, ponieważ nie masz wystarczającej ilości informacji. Tylko dlatego, że nie możesz znaleźć powodu, dla którego ktoś może chcieć coś zrobić, nie czyni tego złym pomysłem. Cokolwiek. (Teraz jestem pewien, że ktoś przyjdzie i powie, że zamiast tego powinieneś mieć puste obiekty, które spełniają pewien wzorzec, o którym czytają na jakimś niejasnym blogu i że programiści powinni naprawdę móc pisać programy bez użyciaif
instrukcji, bla bla.)Jeśli macie umowę, która nigdy nie powinna znajdować się
null
w kontenerze, to od was zależy, czy kontrakt zostanie dotrzymany, prawdopodobnie najlepiej przez zapewnienie. Prawdopodobnie zajęłoby Ci to maksymalnie 10 linii kodu. Java sprawia, że jest to niezwykle łatwe. JDK nie może czytać w twoich myślach.źródło
ensureCapacity(int minCapacity)
metody iArrayList(int initialCapacity)
konstruktora.null
wstępnie przydzielonych (ale jak dotąd nieużywanych ) pozycjiArrayList
; ale możemy na to pozwolićensureCapacity
, a jednocześnie nie pozwolić na inne funkcje, takie jakset
to. Powody podane gdzie indziej wydają się silniejsze.set
element powinien mieć możliwość dowolnej wartości, która może zostać zwróconaget
. Nawet jeśli normalna próbaget
elementu, dla którego zostało przydzielone miejsce, ale nigdy nie zostało napisane, powinna rzucić wyjątek, a nie powrótnull
, nadal przydatne byłoby posiadanie pary metod, które pozwoliłybylist1.setOrEraseIfNull(index, list2.getOrReturnNull(index))
zamiast wymagaćif (list2.valueSet(index)) list1.set(index, list2.get(index)); else list1.unset(index);
Wydaje się, że jest to bardziej filozoficzne pytanie (programowe).
ArrayList
ponieważ klasa użyteczności ma być pomocna w szerokim kontekście możliwych przypadków użycia.W przeciwieństwie do ukrytego twierdzenia, że należy odradzać przyjmowanie wartości null jako wartości prawidłowej, istnieje wiele przykładów, w których wartość null jest całkowicie legalna.
Najważniejszym powodem jest to, że
null
jest todo not know
odpowiednik dowolnego typu odniesienia, w tym typów ram. Oznacza to, że w żadnym wypadku nie można zastąpić wartości null bardziej płynną wersjąnothing
wartości.Załóżmy więc, że przechowujesz liczby całkowite 1, 3, 7 na liście arraylist w odpowiednim indeksie: Z powodu pewnych obliczeń chcesz uzyskać element o indeksie 5, więc tablica powinna zwrócić: „brak przechowywanej wartości”. Można to osiągnąć przez zwrócenie wartości null lub NullObject . W większości przypadków zwracanie wbudowanej wartości null jest wystarczająco wyraziste. Po wywołaniu metody, która może zwrócić wartość null i użyciu jej wartości zwracanej, sprawdzanie wartości zwracanej względem wartości null jest dość powszechne we współczesnym kodzie.
źródło
Wyrok
jest ważny i użyteczny (nie sądzę, że muszę wyjaśniać dlaczego). Przydatne jest również posiadanie zbioru plików, z których niektóre mogą mieć wartość NULL.
Przydatność kolekcji, które mogą zawierać obiekty zerowe, wynika bezpośrednio z użyteczności obiektów, które mogą być zerowe. To jest naprawdę tak proste.
źródło
Łatwiej jest zaakceptować wszystko, niż być restrykcyjnym, a następnie spróbować otworzyć swój projekt po fakcie.
Na przykład, co jeśli jeśli oracle / sun podają tylko NonNullableArrayList, ale chcesz mieć możliwość dodania wartości Null do swojej listy. Jak byś to zrobił? Prawdopodobnie będziesz musiał utworzyć zupełnie inny obiekt, nie możesz użyć rozszerzenia NonNullableArrayList. Zamiast tego, jeśli masz ArrayList, która bierze wszystko, możesz łatwo ją rozszerzyć i zastąpić dodawanie, w którym nie akceptuje wartości zerowych.
źródło
Przydatność null?
Bardzo, jeśli idziesz z listą list, aby modelować płytkę 2D z różnymi pozycjami. Połowa z tych pozycji może być pusta (w losowych współrzędnych), podczas gdy wypełnione nie reprezentują prostej int lub String, ale są reprezentowane przez złożony obiekt. Jeśli chcesz zachować informacje o położeniu, musisz wypełnić puste miejsca wartością null, aby twoja lista.get (x) .get (y)nie prowadzi do przykrych niespodzianek. Aby przeciwdziałać zerowym wyjątkom, możesz sprawdzić wartość null (bardzo popularna) lub możesz użyć Opcjonalnego (co wydaje mi się przydatne w tym przypadku). Alternatywą byłoby wypełnienie pustych miejsc „śmieciowymi” obiektami, które mogą prowadzić do wszelkiego rodzaju bałaganu na drodze. Jeśli Twój test zerowy zawiedzie lub zostanie gdzieś zapomniany, Java poinformuje Cię o tym. Z drugiej strony obiekt zastępczy „śmieci”, który nie jest odpowiednio sprawdzony, może przejść niezauważony.
źródło