Comment émuler un opérateur C # en Java
Question
Il existe des situations dans lesquelles il est pratique de demander à une conversion de type de renvoyer une valeur null au lieu de générer une exception ClassCastException. C # a l'opérateur en tant que
pour le faire. Y at-il quelque chose d’équivalent disponible en Java, vous n’avez donc pas à vérifier explicitement l’exception ClassCastException?
La solution
Voici une implémentation de as, comme suggéré par @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
Autres conseils
Je pense que vous devrez rouler vous-même:
return (x instanceof Foo) ? (Foo) x : null;
EDIT: si vous ne souhaitez pas que votre code client traite les valeurs null, vous pouvez introduire un Null. Objet
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
}
}
Vous pouvez utiliser le mot clé instanceof
à la place du de C #, <
, mais rien ne ressemble à
en tant que
.
Exemple:
if(myThing instanceof Foo) {
Foo myFoo = (Foo)myThing; //Never throws ClassCastException
...
}
Vous pourriez écrire une méthode d’utilité statique comme celle-ci. Je ne pense pas que ce soit très lisible, mais c'est la meilleure approximation de ce que vous essayez de faire. Et si vous utilisez des importations statiques, la lisibilité ne serait pas trop grave.
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;
}
}
Voici un scénario de test qui montre comment cela fonctionne (et que cela fonctionne.)
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);
}
}
En Java 8, vous pouvez également utiliser la syntaxe de flux avec Optional:
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"));
Je pense que vous pourriez probablement créer un en tant qu'opérateur
quelque chose comme
as<T,Type> (left, right)
which evaluates to
if (typeof(left) == right)
return (right)left
else
return null
Je ne sais pas comment vous allez le faire, je suis c # pour le moment et mon chapeau Java est devenu un peu poussiéreux depuis que j'ai quitté l'université.