tags:

views:

485

answers:

9

Is it possibly in java to attempt a cast and get a null if the cast fails?

+13  A: 

You can use the instanceof keyword to determine if you can cast correctly.

return obj instanceof String?(String)obj: null;

Of course it can be genericied and made into the function, but I think question was about what means Java have to accomplish this.

eugener
I'm not sure that's what shoosh wants. Probably a more generic way to treat the cast is needed. This would be the perfect answer for "How do I validated my object is instance of a given class" though :)
OscarRyz
Needs an "else" clause...
Michael Myers
I think we are not here to solve problems for others, but provide guidance. So pointing the right direction should be enough.
eugener
A: 

AFAIK, this would be (one) of the ways to do that:

SomeClassToCastTo object = null;
try {
  SomeClassToCastTo object = SomeClassToCastTo.class.cast(anotherObject);
}
catch (ClassCastException e) {
  object = null;
}

Ugly, but it should do what you want...

Peter
That's not a good case for using the reflective "cast()" method. See http://stackoverflow.com/questions/243811/when-should-i-use-the-java-5-method-cast-of-class for more info.
erickson
Agreed, I had a brain fart and forgot about the `instanceof` operator.
Peter
creating an exception in this case could be avoided. exceptions are objects, so it's nice not to create them unnecessarily.
cd1
A: 

In Java if a cast fails you will get a ClassCastException. You can catch the exception and set the target object to null.

neesh
A: 

you can handle this catching ClassCastException

Rony
Every time an Exception gets thrown, there's a lot of overhead involved. That's why Exceptions should be just that--an "exception." Exception handling should be reserved for events that are truly exceptional. When exceptions become the rule, you're programming wrong. Far better to use type checking.
StriplingWarrior
A: 

You can either catch the exception:

Foo f = null;
try {
  f = Foo(bar);
}
catch (ClassCastException e) {}

or check the type:

Foo f = null;
if (bar instanceof Foo)
  f = (Foo)bar;
Pesto
Empty catch blocks are a very bad habit... actually, I think the compiler should slap you in the face when you do it ;). And anyway, you should never rely on exceptions for something you can check without an exception being thrown.
Thomas Levesque
Which is why I also gave the version without an exception.
Pesto
+5  A: 

You can, but not with a single function in Java:

public B nullCast(Object a) {

  if (a instanceof B) {
     return (B) a;
  } else {
     return null;
  }
}

EDIT: Note that you can't make the B class generic (for this example) without adding the target class (this has to do with the fact that a generic type is not available to instanceof):

public <V, T extends V> T cast(V obj, Class<T> cls) {
  if (cls.isInstance(obj)) {
    return cls.cast(obj);
  } else {
    return null;
  }
}
Kathy Van Stone
Yes, but I was giving the general idea, not a specific method.
Kathy Van Stone
+1  A: 
MyType e = ( MyType ) orNull( object, MyType.class );
// if "object" is not an instanceof MyType, then e will be null.

...

public static Object orNull( Object o , Class type ) { 
    return type.isIntance( o ) ? o : null;
}

I guess this could somehow done with generics also but I think but probably is not what is needed.

This simple method receives Object and returns Object because the cast is performed in the method client.

OscarRyz
+29  A: 
public static <T> T as(Class<T> t, Object o) {
  return t.isInstance(o) ? t.cast(o) : null;
}

Usage:

MyType a = as(MyType.class, new MyType());   
// 'a' is not null

MyType b = as(MyType.class, "");   
// b is null
erickson
@erickson: This is perfect! +10 if I could ( I knew generic could be used here :P ) I added a sample usage , feel free to rollback if you feel like.
OscarRyz
+1 for compile-time safety
dfa
Thanks Oscar, very nice!
erickson
A: 

The two solutions above are somewhat awkward:

Casting and catching ClassCastException: creating the exception object can be expensive (e.g. computing the stack trace).

The nullCast method described earlier means you need a cast method for each cast you want to perform.

Generics fail you because of "type erasure" ...

You can create a static helper method that is guaranteed to return an instance of your target class or null, and then cast the result without fear of exception:

public static Object nullCast(Object source, Class target) {
    if (target.isAssignableFrom(source.getClass())) {
        return target.cast(source);
    } else {
        return null;
    }
}

Sample call:

Foo fooInstance = (Foo) nullCast(barInstance, Foo.class);
Harold L