2012-01-31 7 views
7

El método lastIndexOf() de la interfaz de lista acepta un parámetro que es de tipo Object.¿Por qué el método lastIndexOf() de la interfaz de lista acepta Object como parámetro y no E?

Sin embargo, el método add() acepta un parámetro de tipo E (que es el tipo genérico de la lista que se define en el momento de la creación de una lista) Desde add() sólo acepta E, esto evita que el revelador (o usuario) para agregar cualquier objeto incompatible a la lista en tiempo de compilación en sí.

Ahora, el documento Java dice que lastIndexOf() puede lanzar ClassCastException si el objeto pasado es incompatible. Sin embargo, cuando corro el siguiente código en Eclipse Helios no lo entiendo ninguna excepción: -

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 
} 
} 

En línea 1 y línea 2, que han pasado objetos incompatibles a mi lista de los cuales es de tipo String. Sin embargo, la salida que lo que consigo es: -

5 
-1 
-1 

No me sale ClassCastException.

Si el método lastIndexOf() hubiera estado aceptando objetos de tipo E en lugar de objetos de tipo Object, esto se habría evitado solo en tiempo de compilación. ¿Por qué no se hace esto?

Los creadores de Java deben haber pensado algún problema que podría ocurrir si acepta E (y no Object). ¿Qué daño sería?

+1

mira en http://docs.oracle.com/javase/1.5.0/docs/api/index.html. Se menciona claramente que el argumento es un Objeto y ahora se aplica una excepción. – xyz

Respuesta

1

Aquí hay un ejemplo que podría ayudar. Tenga en cuenta que el método equals utilizado por ArrayList<T> devolverá verdadero si pasó un LinkedList<T> con elementos iguales en el mismo orden. Por lo tanto, si tiene un List<ArrayList<Integer>>, sería válido llamar al lastIndexOf, pasando un LinkedList<Integer>, para encontrar un igual ArrayList<Integer>. Pero si se definió lastIndexOf en la forma que describe, esto no sería posible.

2

No es necesario el tipo E - recordar que los genéricos son sólo tienes que escribir a cuadros azúcar para moldes y equals se define en Object, por lo que no es necesario emitir el artículo para averiguar si es igual a otros artículos en la lista. Además, considere el uso de comodines delimitados. Si su lista se definió como List<? extends Foo>, no podrá obtener el lastIndexOf para ningún artículo que no sea null.

2

Por las mismas razones que Collection.remove (Object o) tiene una firma similar. Vea this question para más detalles.

-1

Una manera posible de pensarlo es por los comodines en Generics.

Imagínese si usted tenía,

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

(Suponiendo que todas las cadenas están en el list). Si List API tenía List.lastIndexOf(E e), entonces, literalmente, con nuestro ejemplo anterior, esto lo haría List.lastIndexOf(? extends Serializable) y no podría pasar un objeto que no sea null.

Esta es la razón por la que ponen Object como tipo de parámetro. Uno debe simplemente implementar el método equals() del objeto correctamente para la búsqueda lastIndexOf().

+0

"esto lo haría List.lastIndexOf (? Extends Serializable) y no podría pasar un objeto que no sea nulo". Y esto es malo porque? Si fuera el caso de que solo los objetos de la misma clase pudieran ser iguales, entonces la restricción que mencionas sería necesaria para hacer cumplir la seguridad del tipo: si no sabemos qué clase son los elementos de la lista, entonces podemos ". t buscar de forma segura un elemento porque ese elemento podría no ser el tipo correcto – newacct

+0

@newacct, es malo, porque el compilador no sabe si es seguro agregar 'String' o' Integer' sin java haciendo [wildcard capture] (http://java.sun.com/j2se/1.5/pdf/generics-tutorial.pdf). Java no sabe si el objeto es un supertipo de lo que usted proporciona. Por lo tanto, es posible que el compilador no acepte el argumento, ya que no es seguro para tipos. Por lo tanto, debemos permitir cualquier tipo ('Object') y hacer una comparación de igualdad. –

+0

No entiendo tu respuesta. Estoy diciendo que la * única * razón por la cual el argumento es tipo 'Objeto' es porque los objetos de diferentes clases pueden ser iguales. Si hipotéticamente Java se hizo de tal manera que el método igual de una clase solo podría tomar un objeto del mismo tipo, entonces 'lastIndexOf()' debería tomar el tipo 'E' por la misma razón que' add() 'toma el tipo' E' - no sería seguro de lo contrario. – newacct

2

En los métodos, como remove, recorrerá el método Array [E] y try equals() en cada objeto, luego lo eliminará por el índice si lo encuentra. El lastIndexOf es el mismo que a continuación.

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; 
} 

Así que si la clase LastIndexOf definir su propia función es igual, y que hacen que sea igual a la cadena "a", entonces, de acuerdo con la especificación de Java del lastIndexOf(new LastIndexOf()) debe ser de vuelta el valor como lastIndexOf("at").

También échale un vistazo aquí. Why aren't Java Collections remove methods generic? Otro What are the reasons why Map.get(Object key) is not (fully) generic

0

lastIndexOf sólo se preocupa por el método equals(). Por lo tanto, es feliz tomando cualquier cosa, y solo explotará si lo hace el método subyacente equals().

Una manera más segura de hacerlo habría sido definir una interfaz "se puede comprobar la igualdad", que funcionaría como Comparable. Pero eso es mucho trabajo y no retrocompatible.

Cuestiones relacionadas