Domanda

Ho implementato questa funzione:

 static <X,Y> Y castOrNull(X obj) {
  try {
   return (Y)obj;
  }
  catch(ClassCastException e) {
   return null;
  }
 }

Questo mi dà l'avviso del compilatore:

Type safety: Unchecked cast from X to Y

Il che io non capisco esattamente. Non è forse il try/catch che sto facendo qui un assegno per esso? Posso ignorare l'avviso?

Sarà il mio lavoro funzione come previsto o no? Come faccio a implementare correttamente?

Ho provato anche con un assegno obj instanceof Y ma che non funziona a causa del modo generici maniglia Java.

Btw., Questa funzione sembra molto utile per me (per fare qualche altro codice più pulito). Mi chiedo se una tale funzione potrebbe già esistere in Java?


Un esempio dove voglio usarlo:

    void removeEmptyRawStrings() {
        for(Iterator<Entity> e = entities.iterator(); e.hasNext();) {
            RawString s = castOrNull(e.next());
            if(s != null && s.content.isEmpty()) e.remove();
        }
    }

Ho casi come questi molto spesso nel mio codice. E credo che questo sia più leggibile e più semplice di qualsiasi altra cosa. Ma per favore mi dia un suggerimento migliore se si dispone di alcuna su come fare quel codice ancora più semplice.

È stato utile?

Soluzione

Quindi, il problema qui è che il parametro generico Y quando viene utilizzato per la fusione dinamica è trattato come Object. Non sarà mai gettare un CCE. Si ottiene un CCE gettato la chiama metodo, la sicurezza di tipo statico, come avete rotto.

Anche X è del tutto inutile qui:

Quasi certamente la soluzione corretta non è quella di tentare qualcosa di simile. null è male. Casting è male.

Tuttavia, se siete determinati a sciocchezze di scrittura, è possibile passare l'oggetto Class:

public static <T> T evilMethod(Class<T> clazz, Object obj) {
    try {
        return clazz.cast(obj);
    } catch (ClassCastException exc) {
        return null;
    }
}

Altri suggerimenti

non sono del tutto sicuro che funzionerà come previsto. (Dipende da ciò che ci si aspetta ovviamente :-) ma questo codice volontà di risultato esempio in una java.lang.ClassCastException ( Ideone ) :

public class Main {

    public static void main(String[] args) {
        Integer o = Main.<String, Integer>castOrNull("hello");
    }


    public static <X, Y> Y castOrNull(X obj) {
        try {
            return (Y) obj;
        } catch (ClassCastException e) {
            return null;
        }
    }
}

@ Tom Hawtin ha il "corretto" soluzione .

È possibile eliminare l'avviso in questo metodo se si sa per certo che non è un problema annotando con @SuppressWarnings("unchecked")

Grazie ai generici Java modo in cui sono state progettate questo codice non funzionerà affatto. I generici sono utili solo per la verifica del tipo di compilazione, come le classi non utilizzano le informazioni di tipo generico in fase di esecuzione.

Il codice verrà compilato a questo:

 static Object castOrNull(Object obj) {
  try {
   return (Object)obj;//FAIL: this wont do anything
  }
  catch(ClassCastException e) {
   return null;
  }
 }

Il cast di oggetto non verrà mai meno, e il codice compilato non ha accesso ai tipi generici presenti al momento della compilazione. Dal momento che il cast non avviene come dovrebbe si riceve un avviso per un'operazione incontrollato.

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