Pregunta

Me han puesto en práctica esta función:

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

Esto me da la advertencia del compilador:

Type safety: Unchecked cast from X to Y

Lo que no entiendo exactamente. No es la try/catch que estoy haciendo aquí un cheque por ello? ¿Puedo pasar por alto la advertencia?

¿Mi trabajo de la función como se espera o no? ¿Cómo iba a aplicar correctamente?

También probé con un cheque obj instanceof Y pero que no funciona debido a la forma del asa genéricos de Java.

Por cierto., Esta función parece bastante útil para mí (para hacer algún otro código más limpio). Me pregunto si tal función puede existir ya en Java?


Un ejemplo donde quiero utilizarlo:

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

Tengo casos como estos muy a menudo en mi código. Y creo que esto es más fácil de leer y más simple que cualquier otra cosa. Pero por favor, dame una idea mejor si tiene alguna acerca de cómo hacer que el código aún más sencilla.

¿Fue útil?

Solución

Así que el problema aquí es que el Y parámetro genérico cuando se utiliza para la fundición dinámica es tratado como Object. Nunca va a lanzar un CCE. Se obtiene una CCE tirado en el llamando a método, la seguridad de tipo estático como se ha roto.

También X es totalmente inútil aquí:

Es casi seguro que la solución correcta no es intentar algo como esto. null es malo. Casting es mala.

Sin embargo, si usted está decidido a escribir sin sentido, se puede pasar el objeto Class:

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

Otros consejos

No estoy seguro del todo que va a funcionar como se espera. (Depende de lo que se espera, por supuesto, pero :-) Este código de resultado instancia en un 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 consiguió la "correcta" solución .

Se puede suprimir la advertencia en este método si conoce a ciencia cierta que no es un problema anotando con @SuppressWarnings("unchecked")

Gracias a los genéricos de Java manera en que diseñaron este código no trabajará en absoluto. Genéricos sólo son útiles para la comprobación de tipos en tiempo de compilación como las clases no utilizan información de tipo genérico en tiempo de ejecución.

Su código se compila a esto:

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

El elenco de objetos nunca fallará, y el código compilado no tiene acceso a los tipos genéricos presentes en tiempo de compilación. Dado que el elenco no sucede como debe recibe una advertencia para una operación sin control.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top