Why Cast After an Instanceof

Why cast after an instanceOf?

Keep in mind, you could always assign an instance of Square to a type higher up the inheritance chain. You may then want to cast the less specific type to the more specific type, in which case you need to be sure that your cast is valid:

Object p1 = new Square();
Square c1;

if(p1 instanceof Square)
c1 = (Square) p1;

java: combined instanceof and cast?

Now, I was told that using this castOrNull function in that way is an evil thing do to. Why is that?

I can think of a couple of reasons:

  • It is an obscure and tricky way of doing something very simple. Obscure and tricky code is hard to read, hard to maintain, a potential source of errors (when someone doesn't understand it) and therefore evil.

  • The obscure and tricky way that the castOrNull method works most likely cannot be optimized by the JIT compiler. You'll end up with at least 3 extra method calls, plus lots of extra code to do the type check and cast reflectively. Unnecessary use of reflection is evil.

(By contrast, the simple way (with instanceof followed by a class cast) uses specific bytecodes for instanceof and class casting. The bytecode sequences can almost certainly will be optimized so that there is no more than one null check and no more that one test of the object's type in the native code. This is a common pattern that should be easy for the JIT compiler to detect and optimize.)

Of course, "evil" is just another way of saying that you REALLY shouldn't do this.

Neither of your two added examples, make use of a castOrNull method either necessary or desirable. IMO, the "simple way" is better from both the readability and performance perspectives.

How cast to subclass of object class without use instanceof in JAVA?

Typecasts cannot be used in a dynamic fashion as you are attempting. Here are some of the problems in what you are trying to do:

(obj.getClass().getName()) obj;

The "stuff" inside the brackets must be an identifier not an expression. That identifier needs to be the name of an actual class or an actual interface that is known at compile time. It cannot be the identifier for a variable. It cannot even be the identifier for a type parameter.

(obj.getClass().getName) nameVariable = ...

This is simply wrong. There is no syntax that would allow you to use a typecast on the left hand side of an assignment like that.


So is it possible to "subclass" an instance avoid using instanceof?

The instanceof is NOT being used to do the subclassing. The type cast is doing that! The instanceof is actually being used to discriminate the subclasses.

It is possible (though probably not what you want!) to discriminate without using instanceof.

  1. Use switch on the class name:

    switch (obj.getClass().getName()) {
    case "a.b.Athletic1":
    Athletic1 a1 = (Athletic1) obj;
    // do stuff
    break;
    ...
    case "a.b.Athletic10":
    Athletic10 a10 = (Athletic10) obj;
    // do stuff
    }

    Problem: you still have boilerplate code to discriminate a fixed number of cases.

  2. Use a Map.

    Map<Class<?>, Consumer<?>> mapping = new Map<> {{
    put(a.b.Athletic1.class,
    o -> {
    Athletic1 a1 = (Athletic1) o;
    // do stuff
    });
    put(a.b.Athletic10.class,
    o -> {
    Athletic10 a10 = (Athletic10) o;
    // do stuff
    });
    }};

    Consumer<Object> c = mapping.get(obj.getClass());
    if (c != null) {
    c.accept(obj);
    }

    Advantages:

    • The map can be populated dynamically.
    • If you need to the Consumer objects could be created dynamically as proxy classes. (Though that is expensive!)

    Disadvantage: still a lot of boilerplate.

While these avoid an explicit instanceof, (IMO) these are just as bad as your existing approach. The "code smell" still exists.


IMO, the real solution is to use Java polymorphism.

  1. Create a commons superclass / interface for the Athletic classes.

  2. Create a method in the superclass / interface that represents the action

  3. Implement the action method in each of the Athletic classes.

  4. Call it ...

Does using instanceof help and java cast type exception hits performance?

  1. If you use instanceOf then you do not need try-catch(ClasscastException e). instanceOf is guaranteed to work, even with nulls.

  2. In today's VMs, casting does not show any measurable performance hit. Rather if you find doing casting too often, then revisit your design.

NOTE: instanceof does not work with Generics due to type erasure.



Related Topics



Leave a reply



Submit