Бывают ситуации, когда практично иметь тип-cast, возвращающий нулевое значение вместо того, чтобы бросать исключение ClassCastException. Для этого C# имеет оператор as
. Есть ли что-то эквивалентное в Java, поэтому вам не нужно явно проверять ClassCastException?Как эмулировать C# as-operator в Java
ответ
Вот реализация, как, как это было предложено @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
Вы можете использовать ключевое слово instanceof
вместо C# is
, но ничего подобного as
.
Пример:
if(myThing instanceof Foo) {
Foo myFoo = (Foo)myThing; //Never throws ClassCastException
...
}
Я думаю, что вам придется свернуть свой собственный:
return (x instanceof Foo) ? (Foo) x : null;
EDIT: Если вы не хотите, чтобы ваш кода клиента, чтобы иметь дело с нулями, то вы можете ввести 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
}
}
Я спекулировать можно Propably creas как оператор
что-то вроде
as<T,Type> (left, right)
which evaluates to
if (typeof(left) == right)
return (right)left
else
return null
Я не знаю, как вы могли бы сделать это, я с # на данный момент, и моя Java шляпа получила немного пыльный, так как я покинул университет.
Сравнение конкретного типа, т. Е. `Typeof (left) == right` не является тем, что` как`. – weston 2013-09-06 08:31:02
Вы можете написать статический метод утилиты, подобный этому. Я не думаю, что это ужасно читаемо, но это лучшее приближение того, что вы пытаетесь сделать. И если вы используете статический импорт, это будет не так уж плохо с точки зрения удобочитаемости.
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;
}
}
Вот тест, который показывает, как она работает (и что это действительно работает.)
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);
}
}
Это не работает. isAssignable Из тестов, чтобы проверить, является ли obj экземпляром суперкласса T. Таким образом, safeCast (новый Object(), A.class) .doA() вернет исключение класса cast, а не NPE. – 2008-09-29 14:43:40
В java 8 вы также можете использовать синтаксис потока с опцией:
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"));
Да, старый двойной литой. У позора Java нет такого элегантного, как оператор «как». – 2008-09-29 14:14:59
«как» - очень полезная вещь. – 2008-09-29 14:16:03