2012-01-05 12 views
23
// Application ... 
Intent i = new Intent(); 
i.putExtra(EXTRA_FILE_UPLOAD_URIS, mGalleryAdapter.getItems()); 

Uri[] getItems() { return mItems; } 

// Service ... 
intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); //works, returns Parcelable[] 
Uri[] uris = (Uri[])intent.getParcelableArrayExtra(EXTRA_FILE_UPLOAD_URIS); 
// ... Breaks with ClassCastException 

Perché il cast Uri[] pausa, quando Uri è Parcelable?Non capisco il motivo per cui questo accade ClassCastException

+0

Inviare lo stacktrace. –

+0

L'elemento 'Uri' viene ereditato da' Parcelable' o viceversa? – fge

+0

Uri implements Parcelable –

risposta

19

Sfortunatamente non è possibile eseguire il cast in questo modo per gli array in Java. Dovrai iterare il tuo array e lanciare ogni oggetto singolarmente.

La ragione di questo è digitare la sicurezza, la JVM semplicemente non può garantire che il contenuto del vostro array possono essere colata a Uri, senza dover scorrere attraverso di loro, che è il motivo per cui si deve iterare loro e li ha gettati singolarmente.

Fondamentalmente poiché Parcelable potrebbe essere ereditato da altri oggetti, non è possibile garantire che la matrice contenga solo oggetti Uri. Tuttavia, il casting per un supertipo funzionerebbe da quel momento in cui la sicurezza del tipo sarebbe stata accettabile.

+0

Ho pensato la stessa cosa (visto che è in quel modo in C#), così ho cercato la covarianza di java array e sembra essere supportato (e di essere un buco nel tipo di sicurezza). Le mie referenze sono semplicemente obsolete con l'attuale JVM? : http://www.angelikalanger.com/Articles/Papers/JavaGenerics/ArraysInJavaGenerics.htm, http://c2.com/cgi/wiki?JavaArraysBreakTypeSafety –

+1

Penso che il tipo safety sia legato ai generici, che è limitato al compilerime . Gli array non sono generati. Sono riferimenti e puoi fare casting. –

+0

giusto, ma il Parcelable [] era un nuovo Uri [] in primo luogo ... quindi deve essere solo se Uri è Parcelable ma Uri [] non è Parcelable [] ... –

0

Penso che quello che sta succedendo è qualcosa come segue:

class Parent { } 

class MaleParent extends Parent { } 

class FemaleParent extends Parent { } 

Se lo scenario è qualcosa come sopra allora quanto segue non riuscirà a runtime:

Parent[] parents = new FemaleParent[]{}; 
MaleParent[] maleParents = (MaleParent[]) parents; 

Qualcosa come segue non solleva l'eccezione :

Parent[] parents = new MaleParent[]{}; 
MaleParent[] maleParents = (MaleParent[]) parents; 
+0

perché così tanti genitori? – Sayka

26

Utilizzare questo metodo, funziona per me.

Parcelable[] ps = getIntent().getParcelableArrayExtra(); 
Uri[] uri = new Uri[ps.length]; 
System.arraycopy(ps, 0, uri, 0, ps.length); 
9

Gli array hanno un comportamento polimorfico - non sono presenti solo tipi generici.

Cioè, se Uri implementa Parcelable poi

si può dire:

Parcelable[] pa = new Uri[size]; 
Uri[] ua = (Uri[]) pa; 

non si può dire:

List<Parcelable> pl = new ArrayList<Uri>(); 

Come vedete siamo in grado di lanciare pa torna a Uri[]. Allora qual è il problema? Questo ClassCastException si verifica quando l'app viene uccisa e successivamente viene ricreato l'array salvato. Quando viene ricreato, il runtime non sa che tipo di array (Uri[]) è stato creato, quindi crea solo un Parcelable[] e inserisce elementi in esso. Da qui il ClassCastException quando provi a lanciarlo su Uri[].

Si noti che l'eccezione non si verifica (in teoria) quando il processo non viene ucciso e l'array originariamente creato (Uri[]) viene riutilizzato tra cicli di salvataggio/ripristino di stato. Come quando cambi l'orientamento.

Volevo solo chiarire PERCHE 'è successo. Se vuoi una soluzione, @solo ha fornito una soluzione decente.

Cheers

+1

Questa è LA risposta giusta. Mi sono imbattuto in ClassCastException che riappare sporadicamente quando il mio servizio ha tentato di trasmettere Parcelable [] dal pacchetto AccountManager all'Account []. È successo molto raramente dopo le telefonate e infine - ecco il colpevole! – user1643723

Problemi correlati