Wie C # als-Operator in Java emulieren
Frage
Es gibt Situationen, in denen es sinnvoll ist, ein haben Typ-Cast einen Nullwert zurückgeben, anstatt eine Classcast zu werfen. C # hat den as
Betreiber, dies zu tun. Gibt es etwas Gleichwertiges in Java so dass Sie sich nicht explizit für den Classcast überprüfen?
Lösung
Hier ist eine Implementierung als, wie @Omar Kooheji vorgeschlagen:
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
Andere Tipps
Ich würde denken, dass Sie rollen müssten Sie Ihre eigenen:
return (x instanceof Foo) ? (Foo) x : null;
EDIT: Wenn Sie nicht Ihre Kundennummer wollen mit Nullen beschäftigen, dann können Sie eine Null Objekt
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
}
}
Sie können das instanceof
Schlüsselwort anstelle von C # 's is
verwenden, aber es gibt nichts wie as
.
Beispiel:
if(myThing instanceof Foo) {
Foo myFoo = (Foo)myThing; //Never throws ClassCastException
...
}
Sie können eine statische Hilfsmethode so schreiben. Ich glaube nicht, es schrecklich lesbar ist, aber es ist die beste Annäherung von dem, was Sie zu tun versuchen. Und wenn Sie statische Importe verwenden würde es nicht so schlimm sein, in Bezug auf die Lesbarkeit.
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;
}
}
Hier ist ein Testfall, der zeigt, wie es funktioniert (und dass es funktioniert.)
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);
}
}
In Java 8 Sie auch Stream-Syntax mit Optional können:
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"));
Ich spekuliert man kann propably creas ein als Operator
so etwas wie
as<T,Type> (left, right)
which evaluates to
if (typeof(left) == right)
return (right)left
else
return null
Ich bin mir nicht sicher, wie Sie es tun würde, ich bin ein C # im Moment und mein Java Hut hat sich ein wenig staubig geworden, seit ich Universität verlassen.