Domanda

Guardando un po 'di codice mi sono imbattuto nel seguente codice

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

e vorrei sapere se il casting in questo modo ha dei vantaggi rispetto a

trTuDocPackTypdBd.update((TrTuDocPackTypeDto)packDto);

Ho chiesto allo sviluppatore responsabile e ha detto di averlo usato perché era nuovo (il che non mi sembra un motivo particolarmente buono), ma sono incuriosito quando vorrei usare il metodo.

È stato utile?

Soluzione

Queste dichiarazioni non sono identiche. Il metodo cast è un normale invocazione del metodo (invokevirtual istruzione JVM) mentre l'altro è un costrutto linguistico (checkcast istruzione). Nel caso che mostri sopra, dovresti usare il secondo modulo: (TrTuDocPackTypeDto) packDto

Il metodo cast viene utilizzato nella programmazione riflessiva con generici, quando si dispone di un'istanza Class per un tipo di variabile. Puoi usarlo in questo modo:

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

Questo ti dà un modo sicuro per evitare l'alternativa errata di semplicemente lanciare un tipo grezzo in un tipo generico:

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

Il compilatore ti avviserà, Unchecked cast from List to List<Widget>, il che significa che tra i puntini di sospensione, qualcuno potrebbe aver aggiunto un Gadget all'elenco non elaborato, che alla fine causerà un ClassCastException quando il chiamante scorre sull'elenco restituito di ( supposto) Widget istanze.

Altri suggerimenti

Il caso principale per farlo (IME) è quando è necessario eseguire il cast sicuro in una classe / metodo generico. A causa della cancellazione del tipo, non è possibile eseguire il cast su T ma se è stato fornito un parametro Class<? extends T>, è possibile utilizzarlo per eseguire il cast e il risultato sarà assegnabile a una variabile di tipo <=>.

Non riesco a trovare un esempio in cui il metodo cast sia possibile e la sintassi del cast no. Tuttavia, guardando il codice, sembra che nel caso in cui il cast non sia possibile, il metodo cast genera una ClassCastException senza informazioni di tipo associate, mentre la sintassi del cast ti darà alcuni suggerimenti (come in & Quot; impossibile cast Snoopy su 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;
}

Con il primo modulo

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

puoi farlo:

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

Con il secondo non puoi. La classe di casting dovrebbe essere hard coded.

Perché dovresti usare una variabile per lanciare al primo posto? Questa è un'altra domanda. :) La prima cosa che mi viene in mente è che non conosci (al momento della compilazione) la classe su cui verrà lanciato.

Entrambe queste affermazioni sono identiche. Scegli quello che ritieni più leggibile. Il secondo metodo è più comune nella mia esperienza ed è quello che preferisco.

Tendo a usare il metodo cast solo quando sto lavorando con la riflessione, e sembra più bello in quella situazione. Tutte le altre volte mi ritrovo a usare il secondo modo di lanciare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top