2008-10-28 10 views
12

Mirando a través de un código me encontré con el siguiente código¿Cuándo debería usar el elenco de clase del método java 5?

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto)); 

y me gustaría saber si la fundición de esta manera tiene alguna ventaja sobre

trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto); 

le he pedido al promotor responsable y él dijo que lo usó porque era nuevo (lo cual no me parece una razón particularmente buena para mí), pero estoy intrigado cuando quisiera usar el método.

+0

vea también http://stackoverflow.com/questions/7900410/why-would-i-use-java-lang-class-cast/7902048#7902048 – irreputable

Respuesta

20

Estas afirmaciones no son idénticas. El método de conversión es una invocación de método normal (instrucción JVM invokevirtual) mientras que el otro es una construcción de lenguaje (instrucción checkcast). En el caso que muestra arriba, debe usar el segundo formulario: (TrTuDocPackTypeDto) packDto

El método cast se utiliza en la programación reflexiva con genéricos, cuando tiene una instancia de clase para algún tipo de variable. Se podía utilizar de esta manera:

public <T> Set<T> find(Class<T> clz, Filter criteria) { 
    List<?> raw = session.find(clz, criteria); /* A legacy, un-generic API. */ 
    Set<T> safe = new HashSet<T>(); 
    for (Object o : raw) 
    safe.add(clz.cast(o)); 
    return safe; 
} 

Esto le da una forma segura de evitar la alternativa incorrecta de simplemente echando un tipo de prima a un tipo genérico:

/* DO NOT DO THIS! */ 
List raw = new ArrayList(); 
... 
return (List<Widget>) raw; 

el compilador advertirá, Unchecked cast from List to List<Widget> , lo que significa que en la elipsis, alguien podría haber agregado un Gadget a la lista sin procesar, lo que eventualmente causará un ClassCastException cuando la persona que llama itera sobre la lista devuelta de (supuesto) Widget instancias.

+0

En un escaneo rápido de la referencia del lenguaje, parece que el 'class.cast()' omitiría la advertencia de 'conversión insegura' que el compilador normalmente mostraría. Como erickson dicho, use la construcción del lenguaje hasta que no pueda. ;-) –

+0

¿Puedes explicar qué es lo que DEBES hacer en el segundo caso? Acabo de encontrarme con esta advertencia de compilación ayer, pero la ignoré porque soy flojo. ¿Estás sugiriendo algo así como List .cast (raw)? –

+0

@Outlaw: para evitar el segundo caso, debe usar algo como lo que proporcioné en el método "buscar" anterior. Es decir, necesita iterar sobre la 'Lista' y probar que cada elemento realmente es un' Widget'. Entonces, estaría bien ignorar la advertencia que recibes de "(List ) en bruto". – erickson

-3

Ambas afirmaciones son idénticas. Elija cualquiera que encuentre más legible. El segundo método es más común en mi experiencia, y es la vez que prefiero.

Tiendo a utilizar el método de conversión solo cuando estoy trabajando con reflexión, y se lee mejor en esa situación. El resto del tiempo me encuentro usando la segunda forma de casting.

4

El caso principal para hacerlo (IME) es cuando necesita emitir de forma segura una clase/método genérico. Debido al borrado de tipo, no puede convertir a T, pero si se le ha proporcionado un parámetro Class<? extends T>, puede usarlo para transmitir y el resultado se podrá asignar a una variable de tipo T.

0

No encuentro un ejemplo en el que el método de conversión sea posible y la sintaxis de conversión no. Sin embargo, mirando el código, parece que en caso de que el molde no sea posible, el método de conversión arroja una excepción ClassCastException sin información de tipo adjunta, mientras que la sintaxis emitida le dará algunos consejos (como en "no se pudo transmitir Snoopy a TyrannosorusRex ") :

/** 
* Casts an object to the class or interface represented 
* by this <tt>Class</tt> object. 
* 
* @param obj the object to be cast 
* @return the object after casting, or null if obj is null 
* 
* @throws ClassCastException if the object is not 
* null and is not assignable to the type T. 
* 
* @since 1.5 
*/ 
public T cast(Object obj) { 
if (obj != null && !isInstance(obj)) 
    throw new ClassCastException(); 
return (T) obj; 
} 
+0

Class.cast() es útil si aún no sabes a qué clase estás lanzando (es decir, reflexión, etc.). En general, primero verifica Class.isInstance (Object) para asegurarte de que no obtendrás un CCE. –

0

Con la primera forma

trTuDocPackTypdBd.update(TrTuDocPackTypeDto.class.cast(packDto)); 

se puede hacer esto:

public void dynamicCast(Class clazz, Object o) { 
    this.x = clazz.cast(o); 
} 

con HT e segundo, no puedes. La clase de casting debe estar codificada.

¿Por qué usarías una variable para lanzar en primer lugar? Esa es otra pregunta.:) Lo primero que viene a la mente es que no sabes (en tiempo de compilación) la clase a la que se lanzará.

Cuestiones relacionadas