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
.
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.
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.
Create a commons superclass / interface for the
Athletic
classes.Create a method in the superclass / interface that represents the action
Implement the action method in each of the
Athletic
classes.Call it ...
Does using instanceof help and java cast type exception hits performance?
If you use
instanceOf
then you do not needtry-catch(ClasscastException e)
.instanceOf
is guaranteed to work, even withnull
s.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
How to Create a Delay in Swing
Random Number with Probabilities
Why Do I Need a Functional Interface to Work with Lambdas
How to Programmatically Inject a Java Cdi Managed Bean into a Local Variable in a (Static) Method
404 Error Redirect in Spring with Java Config
Apache Spark - Foreach VS Foreachpartition When to Use What
Is Executorservice (Specifically Threadpoolexecutor) Thread Safe
Sum All the Elements Java Arraylist
How to Stop the Task Scheduled in Java.Util.Timer Class
Passing an Array or List to @Pathvariable - Spring/Java
Hashcode and Equals for Hashset
Accessing Kotlin Extension Functions from Java