Existen situaciones en las que es práctico hacer que un valor de retorno de fundido de tipo sea nulo en lugar de arrojar una ClassCastException. C# tiene el operador as
para hacer esto. ¿Hay algún equivalente disponible en Java para que no tenga que comprobar explícitamente ClassCastException?Cómo emular C# as-operator en Java
Respuesta
Aquí es una implementación de como, según lo sugerido por @Omar Kooheji:
public static <T> T as(Class<T> clazz, Object o){
if(clazz.isInstance(o)){
return clazz.cast(o);
}
return null;
}
as(A.class, new Object()) --> null
as(B.class, new B()) --> B
Puede usar la palabra clave instanceof
en lugar de C# 's is
, pero no hay nada como as
.
Ejemplo:
if(myThing instanceof Foo) {
Foo myFoo = (Foo)myThing; //Never throws ClassCastException
...
}
Sí, el viejo reparto doble. La vergüenza de Java no tiene algo tan elegante como el operador 'as'. –
'como' es una cosa muy útil. –
yo creo que tendría que rodar su propia:
return (x instanceof Foo) ? (Foo) x : null;
EDIT: Si no desea que su código de cliente para hacer frente a los nulos, entonces se puede introducir un Null Object
interface Foo {
public void doBar();
}
class NullFoo implements Foo {
public void doBar() {} // do nothing
}
class FooUtils {
public static Foo asFoo(Object o) {
return (o instanceof Foo) ? (Foo) o : new NullFoo();
}
}
class Client {
public void process() {
Object o = ...;
Foo foo = FooUtils.asFoo(o);
foo.doBar(); // don't need to check for null in client
}
}
estoy especulando que además probablemente podría Creas un operador como
algo así como
as<T,Type> (left, right)
which evaluates to
if (typeof(left) == right)
return (right)left
else
return null
No estoy seguro de cómo se haría, yo soy una C# en el momento y mi sombrero de Java ha conseguido un poco de polvo desde que salí de la universidad.
Comparación del tipo de hormigón, es decir 'typeof (izquierda) == right' no es lo que' as' hace. – weston
Puede escribir un método de utilidad estático como este. No creo que sea terriblemente legible, pero es la mejor aproximación de lo que estás tratando de hacer. Y si usa importaciones estáticas, no sería tan malo en términos de legibilidad.
package com.stackoverflow.examples;
public class Utils {
@SuppressWarnings("unchecked")
public static <T> T safeCast(Object obj, Class<T> type) {
if (type.isInstance(obj)) {
return (T) obj;
}
return null;
}
}
Aquí es un caso de prueba que muestra cómo funciona (y que funciona.)
package com.stackoverflow.examples;
import static com.stackoverflow.examples.Utils.safeCast;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import org.junit.Test;
public class UtilsTest {
@Test
public void happyPath() {
Object x = "abc";
String y = safeCast(x, String.class);
assertNotNull(y);
}
@Test
public void castToSubclassShouldFail() {
Object x = new Object();
String y = safeCast(x, String.class);
assertNull(y);
}
@Test
public void castToUnrelatedTypeShouldFail() {
Object x = "abc";
Integer y = safeCast(x, Integer.class);
assertNull(y);
}
}
Esto realmente no funciona. isAssignableFrom pruebas para ver si obj es una instancia de una superclase de T. Por lo tanto, safeCast (new Object(), A.class) .doA() devolverá una excepción de clase de lanzamiento, en lugar de un NPE. –
tienes razón. Tenía los dos objetos de clase hacia atrás. He editado la respuesta y debería ser correcta ahora. –
¿Hay alguna razón en particular para utilizar type.isAssignableFrom (obj.getClass() en lugar de type.isInstance (obj)? – VoidPointer
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. Cómo emular a los cierres en c
- 2. Cómo emular CUDA en Windows
- 3. Cómo emular los genéricos de tipo 'signo de interrogación (?)' En Java a C++?
- 4. ¿Cómo se puede emular el espacio de nombres en C?
- 5. Cómo emular la pereza
- 6. Cómo emular onLowMemory()?
- 7. Cómo emular Event.timeStamp
- 8. C# SerialPort - emular el teclado pos
- 9. Cómo emular el ancho mínimo en IE8
- 10. Cómo emular E/S mapeadas en memoria
- 11. ¿Cómo puedo emular punteros en Haskell?
- 12. ¿Cómo emular 'git stash' en fósil, bzr?
- 13. ¿Imitar/emular un comportamiento big-endian en C?
- 14. ¿Cómo puedo emular la búsqueda de Vim * en GNU Emacs?
- 15. Emular/Simular iOS en Linux
- 16. ¿Cómo emular las palabras de transposición de Emacs en Vim?
- 17. ¿Emular una PC vieja?
- 18. ¿Cómo puedo emular ": contiene" usando BeautifulSoup?
- 19. SECCOMP: ¿Cómo emular malloc, realloc y gratis?
- 20. Emular una cámara IP
- 21. Emular Nexus 7
- 22. Perfectamente emular nullptr
- 23. Emular un disco duro en Linux
- 24. ¿Cómo puedo emular la funcionalidad de Solver de Microsoft Excel (GRG no lineal) en C#?
- 25. Emular objeto predeterminado # inspeccionar Salida?
- 26. ¿Cómo debo emular y/o evitar enum en Python?
- 27. ¿Cómo emular la unión etiquetada en una base de datos?
- 28. Android, ¿cómo emular los gestos de deslizamiento en AVD?
- 29. ¿cómo puedo emular el navegador del iPad en Windows
- 30. Cómo emular cp y mv --parent en osx
Aaron, ¿y si quiero pasar un tipo genérico como el parámetro clazz a su función "como"? – mfalto
auto respuesta ... eso no se puede hacer en Java debido al borrado de tipo – mfalto
Me gusta el diseño de la función 'como' anterior, pero me molesta el hecho de que el método' isInstance' se invocará dos veces, debido al uso del método 'cast' de la clase' Clase'.Internamente, este método utiliza el método 'IsIsntance' para verificar la compatibilidad entre los tipos. Sin embargo, podemos esperar que la JVM pueda alinear el código 'moldeado 'dentro de la función' as' dada y luego el Jitter puede eliminar llamadas redundantes al método 'IsInstance', pero no podemos estar seguros de eso. –