Java.util.ArrayList null eklemeye izin veriyor?


41

Neden java.util.ArrayListeklememe izin verdiğimi merak ediyorum null. Ben eklemek istiyorum herhangi bir vaka var mı nullbir etmek ArrayList?

Bir projede bazı kod ekleyerek olan bir hatayı vardı çünkü bu soruyu soruyorum nulliçin ArrayListve hata nerede nokta zordu. Açıkçası bir NullPointerExceptionatılmış, ancak diğer kodlar öğeye erişmeye çalışmadıkça atılmıştı. Sorun, nullnesneyi ekleyen kodun nasıl konumlandırılacağıydı . ArrayListÖğelerin eklendiği kodda bir istisna olsa daha kolay olurdu .


12
Guava Projesi bir sahip bu konuyla ilgili oldukça ilginç sayfasını (onlar izin vermez nullkendi koleksiyonlarının çoğu).
Joachim Sauer

6
Burada verilen cevapların bu soruyu iyi kapsadığına inanıyorum. Belki de belirtilmesi gereken şey şudur: JDK'daki her şeyi kutsal ve mükemmel olarak kabul etmeyin ve ardından neden bu kadar "mükemmel" olduğunu anlamaya çalışırken kafanızı sallayın. Bazı şeyler (dürüst, IMHO) hatalardır, geriye dönük uyumluluk nedeniyle orada kalmışlardır. Java yaratıcıları bile itiraf ediyor, sadece belirli Java API'lerinin eleştirisini görmek için Joshua Bloch'un kitaplarını okudum. Her halükarda, sorunuz hava koşullarına iniyor, Java’da NPE yakalamanın daha zarif bir yolu yok. Cevap hayır, ama olmalı.
Shivan Dragon,

2
Neden izin verilmemesi gerektiği hakkında daha fazla bilgi verebilir misiniz? Bu sadece bir zevk meselesiyse, daha az kısıtlayıcı olan tercih edilmelidir.
Mare Infinitus

Basit cevap null, ister eksik olsun ister olmasın Java'da eksik verileri temsil etmenin varsayılan yoludur. Aslında pek çok insan bundan hoşlanmaz ve fonksiyonel programlama tarzı şeyler için onu tartışır. En çok oy alan cevap hiçbir anlam ifade etmiyor / sorunun özünü yakalamıyor.
xji

@Jiangiang Ne olduğunu basitleştiriyorsun null. “Kayıp” sadece birkaç yorumdan biridir null. Diğer geçerli yorumlar "Bilinmiyor", "Uygulanamaz" veya "Başlatılmamış" olabilir. Ne nulltemsil uygulamaya bağlıdır. Python topluluğunun söyleyeceği gibi, “Belirsizlik karşısında, tahmin etme isteğini reddet.” Bunu yapabilme kabiliyetine sahip bir kapta boş bırakmayı reddetmek, sadece bir tahmin olurdu.
riwalk,

Yanıtlar:


34

Bu tasarım kararı çoğunlukla adlandırma ile belirlenir.

Name ArrayList , dizilere benzer bir işlevsellik okuyucuyu önerir - ve Java Collections Framework tasarımcılarının API kullanıcılarının büyük çoğunluğunun dizilere benzer şekilde çalışacağına güvenmesini beklemesi doğaldır .

Bu özellikle boş elemanların muamelesini içerir. Aşağıdakilerin işe yarayacağını bilen API kullanıcısı:

array[0] = null; // NPE won't happen here

olacağını oldukça şaşırttı ArrayList'deki benzer kod NPE atardı olmadığını öğrenmek için:

arrayList.set(0, null); // NPE => WTF?

Yukarıdaki gibi akıl yürütme, ArrayList ve düz diziler arasında yakın benzerlik gösteren JCF öğretici vurgulama noktalarında sunulmuştur :

ArrayList ... sürekli zamanlı pozisyon erişimi sunar ve sadece düz hızlıdır ...

Eğer bir List uygulamasının boş değerlere izin vermemesini istiyorsanız NonNullableArrayList, API kullanıcılarının kafasını karıştırmamak için buna benzer bir şey ya da onun gibi bir şey çağrılmalıdır .


Yan nota, aşağıda ortaya konan gerekçeleri destekleyen ek hususlarla birlikte aşağıdaki yorumlarda yardımcı bir tartışma vardır .


12
Bu açıklama LinkedList aynı zamandanull liste girişlerini de desteklediğine inandırıcı değildir .
Stephen C

12
Evet ... ama daha basit ve (IMO) daha mantıklı bir açıklama, nullgirişlere izin vermenin birçok durumda yararlı olmasıdır.
Stephen C,

7
Dizi dizisini taklit ettiği için ArrayList böyle çağrılmaz. Bir dizi olarak uygulanan bir liste olduğu için buna denir. Bir TreeMap'in bir Ağaç gibi davranmaması gibi.
Florian F

11
Bu cevap, IMO, sadece düz yanlıştır. Boşluklara izin verilir, çünkü Java'da daha iyi veya daha kötüsü için (IMO, daha kötü) null, başlatılmamış veya eksik değerleri göstermek için çok kullanılır. En çok oyu ve "kabul et" onayını nasıl aldı? Cidden, bugünlerde StackOverflow'a olan inancımı gerçekten yitiriyorum.
user949300 15:14

8
Bu cevap çok açık. Bu sadece liste uygulamasında boş değerlere izin verilmediğine dair desteklenmeyen bir tahmindir. Burada, boş değerlere izin veren / geçersiz kılan Java koleksiyonlarının bir araya getirilmesi; dizilere olan benzerliği ile ilgisi olmadığını fark et .
Andres F.

32

Boş, bir listenin öğesi için geçerli bir değer olabilir. Listenizin, bir kullanıcı listesi hakkında bazı isteğe bağlı verileri temsil eden ve kullanıcılar ile aynı sırada depolanan öğeleri içerdiğini söyleyin. Ekstra veriler doldurulursa, listeniz ek verileri içerecektir, aksi takdirde bir kullanıcıya karşılık gelen yuva boş kalır. (Eminim daha iyi örnekler vardır, ancak fikri anladınız)

null eklenmesine izin vermek istemiyorsanız, dizi listesini null eklendiğinde atılan kendi sarmalayıcınızla sarabilirsiniz.


2
Bu, null değerlere neden izin verilmesi gerektiğinin kötü bir örneği gibi görünüyor - isteğe bağlı verileri temsil etmenin bir listede boş değerler kullanmaktan daha iyi yolları var.
casablanca

@ casablanca evet kesinlikle katılıyorum, bu harika bir örnek değil.
Sam Holder

Bir ArrayList'in bir sonraki geliştiricinin 'keşfetmesi' için kötü sürprizlerden başka boş değerler içermesi için iyi bir neden bulamıyorum: /
AndreasScheinert

7
@casablanca Sizinle aynı fikirdeyim, Java'da isteğe bağlı verileri göstermek için null değerlerinden kaçınılması gerektiğine katılıyorum.
user949300 15:14

2
Sağlam bir kullanım durumu: Parametreleri bir liste olarak bazı dinamik fonksiyonlara geçirmek istiyorsunuz. Her biri farklı bir parametre setine sahip birkaç fonksiyonunuz var, bu yüzden dinamik olarak boyutlandırılmış bir diziye ihtiyacınız var ve geçerli bir fonksiyon argümanı olarak her zaman null değerini geçebilirsiniz!
Falco

19

ArrayListtasarım gereği null sağlar. Bu kasıtlı. Gönderen javadoc :

"[ArrayList, Liste arabiriminin yeniden boyutlandırılabilir bir dizi uygulamasıdır. İsteğe bağlı tüm liste işlemlerini uygular ve boş dahil tüm öğelere izin verir ."

"Neden" cevabı, ArrayList olmasaydı nulllisteye girmenin gerekli olduğu durumlarda kullanılamayacak olmasıdır . Buna karşılık, bir ArrayList'in, değerleri eklemeden önce sınama değerleri yaparak veya bunun olmasını önleyen bir sarıcı kullanarak boş değer içermesini önleyebilirsiniz.

Bir ArrayList'e null eklemek istediğim bir durum var mı?

Açıkçası, nullayrı bir anlamı olan herhangi bir durum . Örneğin, listede belirli bir pozisyondaki değerin başlatılmadığı veya tedarik edilmediği anlamına gelebilir.

ArrayList öğelerinin eklendiği kodda bir istisna atmış olsaydı daha kolay olurdu.

Bir sarmalayıcı sınıfı oluşturarak bu davranışı kolayca uygulayabilirsiniz. Ancak, çoğu programcının / uygulamanın ihtiyaç duyduğu davranış bu değildir .


8

Bir ArrayList'e null eklemek istediğim bir durum var mı?

Tabii, ön tahsisat ne durumda? Bir istemek ArrayListEğer yeterince bilgi olmadığı için henüz oluşturamazsınız şeylerden. Birisinin bir şeyler yapmak isteyebilmesi için bir neden düşünemediğiniz için, bunu kötü bir fikir yapmazsınız. Her neyse. (Şimdi, biri gelir yerine bazı karanlık blogda okumuştum bazı desen yerine getirmek boş nesneler olmalıdır diyecekler eminim ve bu programcılar gerçekten hiç kullanmadan yazma programlarına gerekir if, filan ifadeleri.)

Siz olmalıdır asla bir sözleşme varsa nullbir kapta ler o zaman çok öne sürerek en uygun olasılıkla, emin sözleşme onayladı olduğundan emin olmak için kalmış. Muhtemelen en fazla 10 satır kod almış olacaktı. Java, bu tür şeyleri yapmanızı inanılmaz derecede kolaylaştırır. JDK aklınızı okuyamaz.


1
Önceden dağıtma argümanınız geçersiz, çünkü bu zaten ensureCapacity(int minCapacity)yöntemle ve ArrayList(int initialCapacity)yapıcı ile ArrayList'e yerleştirilmiş .
Philipp

7
@Philipp Bu boşluğa hangi değerleri koyacak?
James

Açık seçim, nullönceden tahsis edilmiş (ancak henüz kullanılmamış ) girişlerine koymaktır ArrayList; ancak bunu başarabiliriz, ancak bunun ensureCapacitygibi başka işlevlere de izin veremeyiz set. Başka bir yerde verilen sebepler daha güçlü görünüyor.
David K,

@DavidK: setBir öğenin iade edebileceği herhangi bir değere mümkün olabileceğini söylemek mantıklı get. Alanın gettahsis edildiği ancak hiç yazılmadığı bir öğeye normal bir girişimde bulunmak null, geri dönmek yerine bir istisna atmak zorunda olsa bile, yine de list1.setOrEraseIfNull(index, list2.getOrReturnNull(index))gerektirmek yerine izin verecek bir çift yönteme sahip olmak yararlı olacaktırif (list2.valueSet(index)) list1.set(index, list2.get(index)); else list1.unset(index);
supercat

1
@DavidK: Tahsis edilmiş ancak henüz yazılmamış bir girişi okumaya çalışmak ya boş vermeli ya da bir istisna atmalıdır; boşa dönmesi daha kolay.
supercat

4

Bu, burada daha çok (yazılım) felsefi bir soru gibi görünüyor.

ArrayList Bir yardımcı sınıf olarak, olası kullanım durumlarının geniş bir bağlamında yardımcı olacak şekilde tasarlanmıştır.

Null değerini geçerli bir değer olarak kabul etmenin gizli iddiasının aksine, boş değerin tamamen yasal olduğu birçok örnek vardır.

Tek ve en önemli nedeni olduğunu nullise do not knowçerçeve tipleri dahil olmak üzere herhangi bir referans türü, eşdeğer. Bu, null nothingdeğerinin daha akıcı bir versiyonu ile hiçbir durumda değiştirilemeyeceği anlamına gelir .

Öyleyse, Tamsayı 1, 3, 7'yi arilistinizde karşılık gelen dizininde sakladığınızı varsayalım: Bazı hesaplamalar nedeniyle, öğeyi dizin 5'te almak istersiniz, yani dizinizin döndürmesi gereken şey: "değer kaydedilmez". Bu, null veya NullObject döndürerek elde edilebilir . Çoğu durumda, yerleşik null değerini döndürmek yeterince etkileyicidir. Bir yöntem çağrıldıktan sonra yapabilirsiniz return null ve dönüş değerini kullanarak boş karşı döndürülen değerin bir onay Modern kodunda oldukça yaygındır.


4

İfade

File f = null;

geçerli ve kullanışlıdır (nedenini açıklamam gerekmiyor sanırım). Aynı şekilde, bazıları boş olabilecek bir dosya koleksiyonuna sahip olmak da yararlıdır.

List<File> files = new ArrayList<File>();
// use my collection of files
// ....
// not using this one anymore:
files.set(3, null);

Boş nesneler içerebilen koleksiyonların kullanışlılığı, doğrudan boş olabilecek nesnelerin kullanışlılığından doğrudan geçer. Gerçekten bu kadar basit.


2

Her şeyi kabul etmek daha kısıtlayıcı olmaktan daha kolay ve sonra tasarımınızı açtıktan sonra denemek daha kolaydır.

Mesela, kahin / güneşte sadece NonNullableArrayList sağladıysa, ama listene Null ekleyebilseydin. Nasıl yapardın? Muhtemelen tamamen farklı bir nesne oluşturmanız gerekecekti, NonNullableArrayList öğesini genişletmek için kullanamazsınız. Bunun yerine, her şeyi alan bir ArrayList'iniz varsa, kolayca uzatabilir ve boş değerleri kabul etmediği bir eklentiyi geçersiz kılabilirsiniz.


2
Aynı fikirde. Çok fazla izin verilmesi, yanlış kullanım yaygın bir kullanım gördüğünde düzeltilmesi daha zordur. Dil tasarımcıları daha sonraki bir aşamada null değerine izin vermiş olsaydı, mevcut programları bozmazdı, ama tam tersi doğru değil.
Andres F.

2
Ama aynı fikirdeyim. İşlevselliği en üst düzeye çıkarmakla ilgilidir. İhtiyaç duymasanız bile boşları kabul eden bir liste kullanabilirsiniz. Gerektiğinde boş değeri reddeden bir liste kullanamazsınız.
Florian F

-1

Boş değerin yararlılığı?

Çok, bu yüzden farklı pozisyonlara sahip bir 2B gerçek yaşam plakasını modellemek için bir Listeyle giderken . Bu konumların yarısı boş olabilir (rastgele koordinatlarda), doldurulmuş olanlar basit bir int veya String değil, karmaşık bir nesne tarafından temsil edilir. Konum bilgisini korumak istiyorsanız, boş noktaları null ile doldurmanız gerekir, böylece list.get (x) .get (y)kötü sürprizlere yol açmaz. Boş değer istisnalarına karşı koymak için boş (çok popüler) olup olmadığını kontrol edebilir veya bir İsteğe Bağlı (bu durumda kullanışlı bulduğum) kullanabilirsiniz. Alternatif, boş noktaları yoldan aşağıya her türlü karışıklığa yol açabilecek "önemsiz" nesnelerle doldurmak olacaktır. Boş çekiniz başarısız olursa veya bir yerde unutulursa, Java size bildirecektir. Öte yandan, düzgün kontrol edilmeyen bir "önemsiz" yer tutucu nesne fark edilmeden geçebilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.