47

Suppose I have two classes deriving from a third abstract class:

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

public class ChildA extends Parent {
    public ChildA {
    }
}

public class ChildB extends Parent {
    public ChildB {
    }
}

In C# I could handle casting in a somewhat type safe manner by doing:

ChildA child = obj as ChildA;

Which would make child == null if it wasn't a ChildA type object. If I were to do:

ChildA child = (ChildA)obj;

...in C# this would throw an exception if the type wasn't correct.

So basically, is there a way to to do the first type of casting in Java? Thanks.

garrettendi
  • 614
  • 2
  • 8
  • 12

7 Answers7

77

I can't think of a way in the language itself, but you can easily emulate it like this:

ChildA child = (obj instanceof ChildA ? (ChildA)obj : null);
Aleks G
  • 56,435
  • 29
  • 168
  • 265
  • 1
    What about obj instanceof List ? (List)obj : null? You can not use instance of for a generic type, because it will disappear at runtime. – vajanko Nov 16 '14 at 10:46
  • 1
    @vajanko You're right, you can't do that with a generic type if you also need to check for type of items. You could still do `List ? (List)obj : null` - but you'll get compile-time warnings. The question didn't say anything about generics. – Aleks G Nov 16 '14 at 18:19
27

In java 8 you can also use stream syntax with 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"));
Dmitry Klochkov
  • 2,484
  • 24
  • 31
20

You can use this method which is compatible with all java types :

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

Example :

// A given object obj
Integer i = safeCast(obj, Integer.class);
Fabienr_75
  • 539
  • 7
  • 15
9

You can use the instanceof operator.

if(obj instanceof ChildA){
     final ChildA child = (ChildA) obj;
}
asenovm
  • 6,397
  • 2
  • 41
  • 52
3

In modern Java you would use

if (obj instanceof ChildA childa) {

}

which is nearly the same in modern C#

if (animal is Dog dog)
{
    // Use dog here
}
Martin Meeser
  • 2,784
  • 2
  • 28
  • 41
2

I think a good way to deal with this is to use generic methods, which is a reusable/safe option as in the following example:

@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);
}

Note that here, the cast only occurs when safe, and it's correct to add the suppressWarnings annotation.

Here's an example of how to call the method:

 Object o = 1;
 int a = coerceTo(o, Integer.class);
ghilesZ
  • 1,502
  • 1
  • 18
  • 30
2

You can always just check first:

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

Or just make a quick method:

public ChildA getInstance(Parent p) {
    if (child instanceof ChildA) {
        return (ChildA) p;
    } else {
        return null;
    }
}
Jon Newmuis
  • 25,722
  • 2
  • 45
  • 57