Подтвердить что ты не робот

Есть ли в Java форма "безопасного типа"?

Предположим, что у меня есть два класса, происходящих от третьего абстрактного класса:

public abstract class Parent{
    public Parent(){
    }
}

public class ChildA extends Parent {
    public ChildA {
    }
}

public class ChildB extends Parent {
    public ChildB {
    }
}

В С# я мог бы обрабатывать кастинг несколько безопасным образом, выполняя следующие действия:

ChildA child = obj as ChildA;

Что бы сделать child == null, если это не объект типа ChildA. Если бы я должен был сделать:

ChildA child = (ChildA)obj;

... в С# это вызовет исключение, если тип был неправильным.

Итак, в принципе, есть ли способ сделать первый тип кастинга в Java? Спасибо.

4b9b3361

Ответ 1

Я не могу придумать способ в самом языке, но вы можете легко подражать ему вот так:

ChildA child = (obj instanceof ChildA ? (ChildA)obj : null);

Ответ 2

В 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"));

Ответ 3

Вы можете использовать оператор instanceof.

if(obj instanceof ChildA){
     final ChildA child = (ChildA) obj;
}

Ответ 4

Вы всегда можете просто проверить сначала:

if (child instanceof ChildA) {
    ChildA child = (ChildA) child;
    // Do stuff.
}

Или просто сделайте быстрый метод:

public ChildA getInstance(Parent p) {
    if (child instanceof ChildA) {
        return (ChildA) p;
    } else {
        return null;
    }
}

Ответ 5

Вы можете использовать этот метод, который совместим со всеми типами java:

public static <T> T safeCast(Object o, Class<T> clazz) {
    return clazz != null && clazz.isInstance(o) ? clazz.cast(o) : null;
}

Пример:

// A given object obj
Integer i = safeCast(obj, Integer.class);

Ответ 6

Я думаю, что лучший способ справиться с этим - использовать общие методы. Это, на мой взгляд, самый многоразовый/безопасный вариант.

Вот, к чему я пришел:

@SuppressWarnings("unchecked")
public <E> E coerceTo(Object o, Class<E> target) throws IllegalArgumentException {
  if(target.isInstance(o)) return (E)o;
  String msg = "expected "+target.getName()+" but was "+o.getClass().getName();
  throw new IllegalArgumentException(msg);
}

Обратите внимание, что здесь литье безопасно, и правильно добавить аннотацию suppressWarnings.

Вот пример вызова метода:

 Object o = 1;
 int a = coerceTo(o, Integer.class);