java: (String []) List.toArray () ClassCastException verir


107

Aşağıdaki kod (android'de çalıştır) bana her zaman 3. satırda bir ClassCastException verir:

final String[] v1 = i18nCategory.translation.get(id);
final ArrayList<String> v2 = new ArrayList<String>(Arrays.asList(v1));
String[] v3 = (String[])v2.toArray();

V2 Nesne [0] olduğunda ve ayrıca içinde Dizeler olduğunda da olur. Herhangi bir fikir neden?


Kovaryans ve Kontravaryans hakkında bilgi almak isteyebilirsiniz - en.wikipedia.org/wiki/…
Hut8

T'nin örnekleme için fabrika yöntemiyle bir arayüz olduğu durum ne olacak?
sebaj

2
@LaceCard - bu sadece dolaylı olarak kovaryans / kontravarlık ile ilgilidir. Asıl mesele, bunun toArray()yöntemin belirtilen davranışının doğrudan bir sonucu olmasıdır .
Stephen C

Yanıtlar:


250

Bunun nedeni, kullandığınızda

 toArray() 

bir String [] 'e dönüştürülemeyen bir Object [] döndürür (içerikler Strings olsa bile) Bunun nedeni, toArray yönteminin yalnızca bir

List 

ve yok

List<String>

jenerikler yalnızca kaynak kodudur ve çalışma zamanında kullanılamaz ve bu nedenle ne tür bir dizi oluşturulacağını belirleyemez.

kullanım

toArray(new String[v2.size()]);

doğru dizi türünü (String [] ve doğru boyutta) ayıran


3
cuz jenerik, bu yüzden
Kaleb Brasee

2
@Kaleb - doğru değil. Ya da en azından asıl sebep bu değil. toArrayToplama sınıfları önce var yöntemler jenerik idi.
Stephen C

10
Bu doğru çözümdür, ancak doğru açıklama değildir. Nesneyi [] Double [] yapamazsınız çünkü bu bir dil özelliği, başka bir şey değil. Generics ile bir alakası yok. Bunun gerçekten bir Double olduğunu varsayarak Object'i Double'a çevirebilirsiniz. Mantıken aynı şeyi bir dizi için de yapabilirsiniz, ancak bu dilin bir parçası değildir. Object'i Double'a çevirirseniz, Object'in aslında Double OLDUĞUNDAN emin olmak için bir çalışma zamanı kontrolü olacaktır. Double to Object çevirirseniz, Object, Double'ın miras hiyerarşisinde olduğu için çalışma zamanı kontrolü yapılmaz.
KyleM

5
Bunu IntelliJ'de yaparken, bunun toArray(new String[0])yerine kullanmak için bir uyarı alıyorum : "Eski Java sürümlerinde, uygun boyutta bir dizi oluşturmak için gerekli olan yansıma çağrısı oldukça yavaş olduğundan, önceden boyutlandırılmış dizi kullanılması öneriliyordu. Ancak, OpenJDK'nin son güncellemelerinden beri bir yarış arasında mümkün olduğu kadar 6 Bu çağrı daha iyi bazen aynı ve boş dizi versiyonunun performansını yapım intrinsified edildi. Ayrıca ön büyüklüğünde dizi geçen bir eşzamanlı koleksiyonu için tehlikelidir sizeve toArrayçağrı."
Mikepote

35

Yanlış kullanıyorsun toArray()

Java'nın jeneriklerinin çoğunlukla sözdizimsel şeker olduğunu unutmayın. Bir ArrayList aslında tüm öğelerinin Dizeler olduğunu bilmez.

Sorununuzu çözmek için arayın toArray(T[]). Senin durumunda,

String[] v3 = v2.toArray(new String[v2.size()]);

Jenerikleştirilmiş formun toArray(T[])geri döndüğüne dikkat edin T[], bu nedenle sonucun açıkça çevrilmesine gerek yoktur.


1
String[] v3 = v2.toArray(new String[0]); 

aynı zamanda hile yapar, yönteme doğru ArrayType verildikten sonra artık cast yapmanıza gerek olmadığını unutmayın.


0
String[] str = new String[list.size()];
str = (String[]) list.toArray(str);

Bunun gibi kullanın.


1
Lütfen! Kodunuzu biçimlendirin! "Ctrl + k" tuşlarına basarak hepsini seçin veya kodun ilk harfinden önce ve son olarak da "` "ekleyin. Ayrıca yanıtı yazarken üstteki yardımdan "{}" öğesini de seçebilirsiniz!
MK
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.