2011-12-27 37 views
19

Supongamos que tengo dos clases derivadas de una tercera clase abstracta:¿Hay alguna forma de fundición "tipo segura" en Java?

public abstract class Parent{ 
    public Parent(){ 
    } 
} 

public class ChildA extends Parent { 
    public ChildA { 
    } 
} 

public class ChildB extends Parent { 
    public ChildB { 
    } 
} 

En C# que podría manejar la fundición de una manera segura tanto escribir haciendo:

ChildA child = obj as ChildA; 

lo que haría niño == null si no era un objeto tipo ChildA. Si tuviera que hacer:

ChildA child = (ChildA)obj; 

... en C# esto arrojaría una excepción si el tipo no fuera correcto.

Entonces, básicamente, ¿hay alguna manera de hacer el primer tipo de fundición en Java? Gracias.

+0

Duplicar : http://stackoverflow.com/questions/148828/how-to-emulate-c-sharp-as-operator-in-java –

+0

Disculpas. Busqué "tipo seguro de java de fundición". No se me ocurrió buscar "como palabra clave java". – garrettendi

+3

Y luego explota con un NPE. ;) –

Respuesta

47

No puedo pensar en una manera en la propia lengua, pero se puede imitar fácilmente de esta manera:

ChildA child = (obj instanceof ChildA ? (ChildA)obj : null); 
+0

¿Qué pasa con obj instanceof List ? (Lista ) obj: null? No puede usar la instancia de para un tipo genérico, porque desaparecerá en el tiempo de ejecución. – vajanko

+0

@vajanko Tiene razón, no puede hacer eso con un tipo genérico si también necesita verificar el tipo de artículos. Todavía podrías hacer 'List? (Lista) obj: null' - pero obtendrá advertencias en tiempo de compilación. La pregunta no decía nada sobre los genéricos. –

5

Puede usar el operador instanceof.

if(obj instanceof ChildA){ 
    final ChildA child = (ChildA) obj; 
} 
2

siempre puede comprobar primero:

if (child instanceof ChildA) { 
    ChildA child = (ChildA) child; 
    // Do stuff. 
} 

o simplemente hacer un método rápido:

public ChildA getInstance(Parent p) { 
    if (child instanceof ChildA) { 
     return (ChildA) p; 
    } else { 
     return null; 
    } 
} 
9

en java 8 también puede usar la sintaxis de flujo con Opcional:

Object o = new Integer(1); 

    Optional.ofNullable(o) 
      .filter(Number.class::isInstance) 
      .map(Number.class::cast) 
      .ifPresent(n -> System.out.print("o is a number")); 
1

Creo que la mejor manera de lidiar con esto es usar métodos genéricos. Esta es, en mi opinión, la opción más reutilizable/segura.

Esto es lo que he venido a:

@SuppressWarnings("unchecked") 
public <E> E coerceTo(Object o, Class<E> target) throws IllegalArgumentException { 
    if(target.isInstance(o)) return (E)o; 
    String msg = "expected "+target.getName()+" but was "+o.getClass().getName(); 
    throw new IllegalArgumentException(msg); 
} 

Tenga en cuenta que aquí, el elenco es seguro y es correcto sumar los suppressWarnings anotación.

Aquí hay un ejemplo de cómo llamar al método:

Object o = 1; 
int a = coerceTo(o, Integer.class); 
2

Usted puede utilizar este método que es compatible con todos los tipos de Java:

public static <T> T safeCast(Object o, Class<T> clazz) { 
    return clazz != null && clazz.isInstance(o) ? clazz.cast(o) : null; 
} 

Ejemplo:

// A given object obj 
Integer i = safeCast(obj, Integer.class); 
Cuestiones relacionadas