2012-04-13 13 views
5

Tengo un método que toma un List<?> como argumento.Java argumentos de tipo genérico

public static String method(List<?> arg){ 
    // Do something based on type of the list 
} 

//I call the method as below 
List<ClassA> listA = new ArrayList<ClassA>(); 
List<ClassB> listB = new ArrayList<ClassB>(); 
method(listA); 
method(listB); 

En method, ¿cómo sé si es una argList de ClassA o una List de ClassB?

+2

Declarar el tipo de parámetro como '' significa exactamente que no está interesado en el tipo real. – biziclop

+0

duplicado de este http://stackoverflow.com/questions/1942644/get-generic-type-of-java-util-list – evanwong

+0

@evanwong - no estoy seguro si estaría de acuerdo con que es un engaño. – djangofan

Respuesta

3

Desde una respuesta por parte del usuario llamado Romain "Si utiliza <?>, Que significa que no va a utilizar el tipo parametrizado en cualquier lugar. Cualquiera de ir al tipo específico (en su caso parece Lista < String>) o al muy genérico Lista < Objeto> "

Además, creo que si utiliza el signo de interrogación, el compilador no detectará desajustes de tipos hasta el tiempo de ejecución (reified; p.119 de Effective Java), omitiendo el borrado y de manera efectiva ¿eliminando el beneficio que obtiene de usar tipos genéricos?

PARA responder la pregunta del consultante: si utiliza List < Object> y luego intenta convertirlo en A o en B, posiblemente utilizando instanceOf, esa podría ser una forma de saber qué es. Aunque creo que hay una forma mejor de hacerlo que eso.

+1

+1 para OP está eliminando de manera efectiva el beneficio que obtiene al usar tipos genéricos. – jahroy

+1

significa "No estoy usando genéricos, pero quiero deshacerme de la advertencia del compilador". – user949300

+3

-1 porque esta respuesta fomenta la mala práctica de codificación. Definir un método que tome un argumento de tipo genérico es la forma adecuada de hacerlo: le da seguridad de tipo y no requiere fundición desordenada. Ver la respuesta de jahroy. –

1

Dado su ejemplo, no hay forma de saber cuáles son los argumentos de tipo genérico a List. Se borran en un nivel de instancia.

14

punto de vista técnico, que CAN uso instanceof para comprobar si un objeto es un tipo determinado.

Sin embargo ... Eso es NOT una buena idea.

La forma en que se ha declarado su método, que puede aceptar una lista de cualquier tipo, por lo que no es necesariamente va a ser A o B.

Es difícil saber lo que estás tratando de hacer , pero probablemente debas hacer que tu método sea genérico.

Puede hacerlo de esta manera:

public static <T> String method(List<T> arg) { 
    // We now know that the type of the list is T, which is 
    // determined based on the type of list passed to this 
    // method. This would demonstrate the point better if 
    // the return type was T, but I'm leaving the return type 
    // as String, because that's what your code returns. 
} 

Aquí hay un ejemplo mejor:

Si desea crear un método genérico que se devuelve el primer elemento de una lista, lo haría así:

public static <T> T firstElement(List<T> theList) { 
    if (theList == null) { 
     return null; 
    } 
    T objectOfTypeT = theList.get(0); 
    return objectOfTypeT; 
} 

Tenga en cuenta que el retorno tipo ahora es T.

Como hemos hecho este método genérico, puede devolver el mismo tipo que se utiliza en la Lista.

Normalmente solo devolvería theList.get(0), pero agregué una línea para hacer más obvio el propósito de los genéricos.

Explicación de la sintaxis:

  • El <T> indica que este método toma un parámetro de tipo llamado T.

  • El T que sigue inmediatamente es el tipo de retorno (al igual que lo haría normalmente return String, Integer, etc ...).

  • El T en el parámetro Lista es como el compilador sabe qué diablos es T.

Esto permite que el compilador para decir: "Este método espera algo de tipo T. Oh, mira ... La lista es también de tipo T. Si alguien pasa una lista de cadenas de este método, que T debe ser una cadena. Si alguien pasa una lista de números enteros a este método, T debe ser un entero. "

por el contrario, el método puede única devolver una cadena y no tiene idea de qué tipo se utiliza en la lista.


también ...

Si A y B se usan para extender la misma clase, llamada TheParentClass, se podría declarar su método como este:

public static String method(List<? extends TheParentClass> arg) 

De esa manera, sabrías un poco más sobre los tipos posibles de su parámetro (y puede beneficiarse de la verificación del tipo de tiempo de compilación).

+0

Ese último ejemplo que dio de "? Extends TheParentClass" es probablemente cómo? fue "significado" para ser utilizado. Permitir el uso de un? sin el bit de extensión es, como sugiere David Mason, una mala práctica pero legal. Creo que a Jahroy se le debe otorgar la respuesta a esta pregunta en lugar de a mí porque él la encasilló. – djangofan

Cuestiones relacionadas