Как эмулировать C # как оператор в Java - PullRequest
48 голосов
/ 29 сентября 2008

Существуют ситуации, когда целесообразно, чтобы приведение типа возвращало нулевое значение, а не генерировало ClassCastException. C # имеет оператор as, чтобы сделать это. Есть ли в Java что-то эквивалентное, поэтому вам не нужно явно проверять исключение ClassCastException?

Ответы [ 6 ]

52 голосов
/ 29 сентября 2008

Вот реализация as, предложенная @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
25 голосов
/ 29 сентября 2008

Я бы подумал, что вам придется бросить свой собственный:

return (x instanceof Foo) ? (Foo) x : null;

РЕДАКТИРОВАТЬ: Если вы не хотите, чтобы ваш клиентский код имел дело с нулями, тогда вы можете ввести 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
    }
}
15 голосов
/ 29 сентября 2008

Вы можете использовать ключевое слово instanceof вместо is в C #, но нет ничего похожего на as.

Пример:

if(myThing instanceof Foo) {
   Foo myFoo = (Foo)myThing; //Never throws ClassCastException
   ...
}
11 голосов
/ 29 сентября 2008

Вы можете написать статический служебный метод, подобный этому. Я не думаю, что это ужасно читаемо, но это лучшее приближение того, что вы пытаетесь сделать. И если вы используете статический импорт, это не будет слишком плохо с точки зрения читабельности.

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);
    }
}
3 голосов
/ 12 февраля 2016

В 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"));
0 голосов
/ 29 сентября 2008

Я полагаю, что вы, вероятно, могли бы назвать оператором

что-то вроде

as<T,Type> (left, right)  
which evaluates to 
if (typeof(left) == right)
   return (right)left
else
    return null

Я не уверен, как ты это сделаешь, я на данный момент c #, и моя шляпа Java стала немного пыльной с тех пор, как я покинул университет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...