2012-01-31 9 views
7

Il metodo lastIndexOf() dell'interfaccia Elenco accetta un parametro che è di tipo Oggetto.Perché il metodo lastIndexOf() dell'interfaccia Elenco accetta Oggetto come parametro e non E?

Tuttavia, il metodo add() accetta un parametro di tipo E (che è il generico tipo di elenco che è definita al momento della creazione di un elenco) Da add() accetta solo E, ciò impedisce lo sviluppatore (o utente) per aggiungere qualsiasi oggetto incompatibile alla lista in fase di compilazione stessa.

Ora, il documento Java dice che lastIndexOf() può lanciare ClassCastException se l'oggetto passato è incompatibile. Tuttavia, quando si esegue il seguente codice in Eclipse Helios non ottengo alcuna eccezione: -

package scjp.collection.list; 

import java.util.ArrayList; 
import java.util.List; 

public class LastIndexOf { 
public static void main(String[] args) { 
    List<String> list = new ArrayList<String>(); 

    list.add("some"); 
    list.add("thing"); 
    list.add("at"); 
    list.add("last"); 
    list.add("and"); 
    list.add("at"); 
    list.add("again"); 



    System.out.println(list.lastIndexOf("at")); 
    System.out.println(list.lastIndexOf(10));     // # 1 
    System.out.println(list.lastIndexOf(new LastIndexOf()));  // # 2 
} 
} 

Alla Linea 1 e Linea 2, mi sono passati oggetti incompatibili alla mia lista, che è di tipo String. Tuttavia, l'output che ottengo è: -

5 
-1 
-1 

non ottengo ClassCastException.

Se il metodo lastIndexOf() avesse accettato oggetti di tipo E anziché oggetti di tipo Object, questo sarebbe stato impedito solo in fase di compilazione. Perché non è fatto ??

I creatori Java devono aver pensato ad un problema che potrebbe verificarsi se accetta E (e non Object). Che male sarebbe ??

+1

guardare http://docs.oracle.com/javase/1.5.0/docs/api/index.html. È chiaramente menzionato che l'argomento è un oggetto e ora l'eccezione è trown. – xyz

risposta

1

Ecco un esempio che potrebbe essere d'aiuto. Si noti che il metodo equals utilizzato da ArrayList<T> restituirà true se viene passato un LinkedList<T> con elementi uguali nello stesso ordine. Quindi, se hai un List<ArrayList<Integer>>, sarebbe valido chiamare lastIndexOf su di esso, passando un LinkedList<Integer>, per trovare un uguale ArrayList<Integer>. Ma se lastIndexOf sono stati definiti nel modo in cui descrivi, questo non sarebbe possibile.

2

Non è necessario il tipo E - ricorda che i generici sono solo digitare-controllato zucchero per calchi e equals è definito sulla Object, quindi non c'è bisogno di lanciare la voce per sapere se è pari a altri articoli nell'elenco. Inoltre, considera l'utilizzo di caratteri jolly limitati. Se l'elenco è stato definito come List<? extends Foo>, non sarà possibile ottenere lastIndexOf per qualsiasi articolo diverso da null.

2

Per gli stessi motivi per cui Collection.remove (Object o) ha una firma simile. Vedi this question per maggiori dettagli.

-1

Un modo possibile per pensarci, è a causa dei caratteri jolly in Generics.

Immaginate di avere,

List<? extends Serializable> list = new ArrayList<> extends Serializable>(); 

(Supponendo che tutte le stringhe sono in list). Se l'API List aveva List.lastIndexOf(E e), quindi, letteralmente, con il nostro esempio sopra, questo lo renderebbe List.lastIndexOf(? extends Serializable) e non potreste davvero passare un oggetto diverso da null.

Questo è il motivo per cui hanno inserito Object come tipo di parametro. Uno dovrebbe solo implementare correttamente il metodo equals() dell'oggetto per la ricerca lastIndexOf().

+0

"questo lo renderebbe List.lastIndexOf (? Estende Serializable) e non potreste davvero passare un oggetto diverso da null." E questo è male perché? Se fosse il caso che solo gli oggetti della stessa classe potessero essere uguali, allora la restrizione che citi sarebbe davvero necessaria per rafforzare la sicurezza del tipo - se non sappiamo quale classe siano gli elementi della lista, allora possiamo ' t cercare in sicurezza un elemento perché quell'elemento potrebbe non essere il tipo corretto – newacct

+0

@newacct, È cattivo, perché il compilatore non sa se è sicuro aggiungere 'String' o' Integer' senza java che fa [wildcard capture] (http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf). Java non sa se l'Oggetto è supertipo di ciò che fornisci. Pertanto, il compilatore potrebbe non accettare l'argomento poiché non è sicuro dal tipo. Quindi, dobbiamo consentire qualsiasi tipo ('Object') e fare un confronto di uguaglianza. –

+0

Non capisco la tua risposta. Sto dicendo che il * solo * motivo per cui l'argomento è di tipo 'Object' è perché gli oggetti di classi diverse possono essere uguali. Se ipoteticamente Java fosse realizzato in modo tale che il metodo equals di una classe potesse prendere solo un oggetto dello stesso tipo, allora 'lastIndexOf()' dovrebbe effettivamente prendere tipo 'E' per la stessa ragione per cui' add() 'prende tipo' E' - altrimenti non sarebbe al sicuro. – newacct

2

Nei metodi, come remove, attraversa la matrice [E] e prova il metodo equals() su ciascun oggetto, quindi rimuove dall'indice se trovato. Lo lastIndexOf è lo stesso di seguito.

public int lastIndexOf(Object o) { 
    if (o == null) { 
     for (int i = size-1; i >= 0; i--) 
     if (elementData[i]==null) 
      return i; 
    } else { 
     for (int i = size-1; i >= 0; i--) 
     **if (o.equals(elementData[i]))** 
      return i; 
    } 
    return -1; 
} 

Quindi, se la classe LastIndexOf definire un proprio uguale funzione e si rendono uguale a stringa "a", poi in base alla specifica Java il lastIndexOf(new LastIndexOf()) dovrebbero essere di ritorno il valore come lastIndexOf("at").

Controllare anche qui. Why aren't Java Collections remove methods generic? Un altro What are the reasons why Map.get(Object key) is not (fully) generic

0

lastIndexOf si preoccupa solo di equals() metodo. Quindi è felice di prendere qualsiasi cosa, e esploderà solo se il metodo sottostante equals() lo fa.

Un modo più sicuro per farlo sarebbe stato definire un'interfaccia "può essere controllata per l'uguaglianza con", che funzionerebbe un po 'come Paragonabile. Ma è un modo per lavorare molto e non è compatibile con le versioni precedenti.

Problemi correlati