useful method generic example are java generics language-construct

method - java generics example



¿Por qué usaría java.lang.Class.cast (9)

Posible duplicado:
¿Cuándo debo usar el método java 5 de clase?

Recientemente me topé con un trozo de código que decía así:

Object o = .. ; Foo foo = Foo.class.cast(o);

En realidad, ni siquiera era consciente de que java.lang.Class tenía un método de conversión, por lo que examiné los documentos, y de lo que deduzco esto simplemente hace una conversión a la clase que representa el objeto Class. Así que el código de arriba sería aproximadamente equivalente a

Object o = ..; Foo foo = (Foo)o;

Así que me pregunté por qué querría usar el método de lanzamiento en lugar de simplemente hacer un reparto "a la manera antigua". ¿Alguien tiene un buen ejemplo donde el uso del método de lanzamiento es beneficioso en comparación con hacer el lanzamiento simple?


En Java a menudo hay más de una forma de despellejar a un gato. Dicha funcionalidad puede ser útil en los casos en los que tenga un código de marco. Imagine un método que acepta una instancia de objeto de clase y una instancia de objeto y devuelve el caso de objeto como la clase:

public static void doSomething(Class<? extends SomeBaseClass> whatToCastAs,Object o) { SomeBaseClass castObj = whatToCastAs.cast(o); castObj.doSomething(); }

En general, use el casting más simple, a menos que no sea suficiente.


En algunos casos, solo conoce el tipo para lanzar un objeto durante el tiempo de ejecución, y ahí es cuando tiene que usar el método de conversión.


La muestra común para eso es cuando recuperas de la capa persistente una colección de entidades a las que se hace referencia con un objeto de clase y algunas condiciones. La colección devuelta podría contener objetos sin marcar, por lo que si solo la convierte como G_H señalada, lanzará la Excepción de lanzamiento en este punto, y no cuando se acceda a los valores.

Un ejemplo de esto es cuando recupera una colección de un DAO que devuelve una colección no verificada y en su servicio que itera sobre ella, esta situación puede llevar a una excepción ClassCastException.

Una forma de resolverlo, ya que tiene la clase deseada y la colección no verificada, se itera sobre ella y se coloca dentro del DAO transformando la colección en una colección marcada y luego la devuelve.


No creo que se use a menudo exactamente como lo has mostrado. El uso más común que he visto es cuando las personas que usan genéricos están tratando de hacer el equivalente a esto:

public static <T extends Number> T castToNumber(Object o) { return (T)o; }

Lo que realmente no hace nada útil debido a la eliminación de tipos.

Mientras que esto funciona, y es de tipo seguro (módulo ClassCastExceptions ):

public static <T extends Number> T castToNumber(Object o, Class<T> clazz) { return clazz.cast(o); }

EDIT : par de ejemplos de uso de google guava:


No hay absolutamente ninguna razón para escribir Foo.class.cast(o) , es equivalente a (Foo)o .

En general, si X es un tipo confiable y un clazz de Class<X> clazz , clazz.cast(o) es igual que (X)o .

Si todos los tipos son confiables, el método Class.cast() es, por lo tanto, redundante e inútil.

Desafortunadamente, debido a la eliminación en la versión actual de Java, no todos los tipos son confiables. Por ejemplo, las variables de tipo no son confiables.

Si T es una variable de tipo, cast (T)o no está marcada, porque en el tiempo de ejecución, el tipo exacto de T es desconocido para JVM, JVM no puede probar si o es realmente tipo T El lanzamiento puede permitirse erróneamente, lo que puede provocar problemas más adelante.

No es un gran problema; por lo general, cuando el programador lo hace (T)o , ya ha razonado que el reparto es seguro y no causará ningún problema en el tiempo de ejecución. El reparto está controlado por la lógica de la aplicación.

Supongamos que un Class<T> clazz está disponible en el punto de lanzamiento, entonces sabemos qué T está en tiempo de ejecución; podemos agregar un control de tiempo de ejecución adicional para asegurarnos de que o sea ​​una T

check clazz.isInstance(o); (T)o;

Y esto es esencialmente lo que hace Class.cast() .

Nunca esperaríamos que el reparto fallara en ningún caso, por lo tanto, en una aplicación correctamente implementada, verifique clazz.isInstance(o) siempre debe tener éxito, por clazz.cast(o) tanto, clazz.cast(o) es equivalente a (T)o - una vez más, bajo La suposición de que el código es correcto.

Si se puede demostrar que el código es correcto y que la conversión es segura, se podría preferir (T)o a clazz.cast(o) por motivos de rendimiento. En el ejemplo de MutableClassToInstanceMap planteado en otra respuesta, podemos ver obviamente que el reparto es seguro, por lo tanto simple (T)o hubiera sido suficiente.


Porque podrías tener algo de esto:

Number fooMethod(Class<? extends Number> clazz) { return clazz.cast(var); }


Un "cast" en Java, por ejemplo, (Number)var , donde la cosa dentro de los paréntesis es un tipo de referencia, realmente consta de dos partes:

  • Tiempo de compilación: el resultado de la expresión de conversión tiene el tipo del tipo al que se convierte
  • Tiempo de ejecución: inserta una operación de verificación, que básicamente dice, si el objeto no es una instancia de esa clase, luego lance una ClassCast Exception (si lo que está convirtiendo es una variable de tipo, entonces la clase que verifique sería el límite inferior de la variable de tipo)

Para utilizar la sintaxis, debe conocer la clase en el momento de escribir el código. Supongamos que no sabes en qué momento de la clase de compilación quieres elegir; Solo lo sabes en tiempo de ejecución.

Ahora te preguntarías, entonces ¿cuál es el punto de casting? ¿No es el punto de conversión para convertir la expresión en el tipo deseado en tiempo de compilación? Entonces, si no conoce el tipo en tiempo de compilación, entonces no hay beneficio en tiempo de compilación, ¿verdad? Es cierto, pero eso es sólo el primer elemento anterior. Está olvidando el componente de tiempo de ejecución de una conversión (segundo elemento anterior): compara el objeto con la clase.

Por lo tanto, el propósito de una Class.cast() tiempo de ejecución (es decir, Class.cast() ) es verificar que el objeto sea una instancia de la clase, y si no, lanzar una excepción. Es aproximadamente equivalente a esto pero más corto:

if (!clazz.isInstance(var)) throw new ClassCastException();

Algunas personas han mencionado que Class.cast() también tiene un buen tipo de retorno que se basa en el parámetro de tipo de la clase pasada, pero que es solo una característica de tiempo de compilación que proporciona un reparto de tiempo de compilación de todos modos. Entonces para ese propósito no tiene sentido usar Class.cast() .


class.cast está diseñado para el tipo de genéricos.

Cuando construyes una clase con el parámetro genérico T, puedes pasar una clase. A continuación, puede realizar el reparto con una comprobación tanto estática como dinámica, que (T) no le proporciona. Tampoco produce advertencias sin marcar, porque está marcada (en ese punto).


Desde Java Class.cast () vs. operador cast

Solo he usado Class.cast (Objeto) para evitar advertencias en "terrenos genéricos". A menudo veo métodos haciendo cosas como esta:

@SuppressWarnings("unchecked") <T> T doSomething() { Object o; // snip return (T) o; }

A menudo es mejor reemplazarlo por

<T> T doSomething(Class<T> cls) { Object o; // snip return cls.cast(o); }

Ese es el único caso de uso de Class.cast (objeto) que he encontrado.