Does Java Casting Introduce Overhead? Why

Does Java casting introduce overhead? Why?

There are 2 types of casting:

Implicit casting, when you cast from a type to a wider type, which is done automatically and there is no overhead:

String s = "Cast";
Object o = s; // implicit casting

Explicit casting, when you go from a wider type to a more narrow one. For this case, you must explicitly use casting like that:

Object o = someObject;
String s = (String) o; // explicit casting

In this second case, there is overhead in runtime, because the two types must be checked and in case that casting is not feasible, JVM must throw a ClassCastException.

Taken from JavaWorld: The cost of casting

Casting is used to convert between
types -- between reference types in
particular, for the type of casting
operation in which we're interested
here.

Upcast operations (also called
widening conversions in the Java
Language Specification) convert a
subclass reference to an ancestor
class reference. This casting
operation is normally automatic, since
it's always safe and can be
implemented directly by the compiler.

Downcast operations (also called
narrowing conversions in the Java
Language Specification) convert an
ancestor class reference to a subclass
reference. This casting operation
creates execution overhead, since Java
requires that the cast be checked at
runtime to make sure that it's valid.
If the referenced object is not an
instance of either the target type for
the cast or a subclass of that type,
the attempted cast is not permitted
and must throw a
java.lang.ClassCastException.

Java: Does primitive type casts performance impact?

A typecast from long to int just ignores the leading 32 bit, so it should be more or less for free.

Long (=64 bit) operations are more expensive on 32 bit CPUs -- a 32 bit CPU will need two machine instructions to add two 64 bit numbers (other operations may take many more). On 64 bit CPUs, there shouldn't be a difference in terms of CPU time.

The (implicit) cast the other way around (from int to long) requires a "sign extension", which means the high bits are filled from the highest bit of the smaller type. So it may actually have a (small) cost, as it is not just ignoring the high bits, but needs to bring them into a well-defined state.

Casting performance in Java

What is the performance impact of such
a cast?

As compared to handling a HTTP request? Absolutely none. If you were doing it in a deeply nested loop that does little else it might matter, but not when it's done once for a task that involves things that are literally millions of times more work (like doing DB requests or accessing the harddisk).

Why does a String-casting loop seem to have a static overhead?

The benchmark is flawed, as most questions in SO and elsewhere related to benchmarking Java code. You are measuring much much much more things than you imagine, such as the JIT compiling methods, HotSpot optimizing loops, etc.

Check http://www.ibm.com/developerworks/java/library/j-jtp02225/index.html .

Also, server VM and client VM behave differently (the JVM starts up faster in client but runs slower for some time, because it starts interpreting the bytecode while it gets compiled, while the server VM compiles it before running), etc.

The GC might also be interfering, more so if you get any Full GC during your benchmark (usually Full GCs completely pause every other thread). Even minor collections might have some impact, since they can use quite a bit of CPU to clean up a possibly huge mess created inside the loops.

To do a proper benchmark you should "warm up" the JVM, turn on lots of output from the JVM to be sure about what you are measuring, etc.

Check this question here on SO which addresses how to write benchmarks in Java, including the topics I mentioned above and much more in great detail: How do I write a correct micro-benchmark in Java?

How much processing and memory use does casting take in Java?

It seems from your code snippet that getSameInstance() returns a SubClass. In this case the simplest solution is

SubClass objectB = getSameInstance();
objectB.functionOne();
objectB.functionOther();

No casts, no worries :-)

As others have rightly noted, the primary concern should be code readability and simplicity, not performance. Optimize only when you know that you need to, and have proven (using a profiler) where the bottleneck is within your code. Even in this case, micro-optimization is rarely useful in Java.

An additional note: calling the same method twice can be problematic if the method is heavy (in which case you are effectively making your code slower, not faster), or has side effects (in which case the behaviour of your program may noticeably change).

And btw in this line of your code snippet

SuperClass objectA = (SuperClass) getSameInstance();

there is absolutely no need to upcast the returned value to SuperClass - a superclass reference can always point to a subclass object. (I guess that such an upcast would be omitted by the compiler anyway, so it makes no difference in the bytecode.)

Update

You still haven't published the declaration of the method I asked for. But from your explanation I presume it should look something like

public Shape getSomeRandomShape();

is this correct?

This would btw mean that your 2nd original code snippet (with the getSameInstance() call) is incorrect - the casts should be the opposite way. You managed to confuse me with it, so you got a confusing answer :-)

Also in the latest examples, you don't need to cast the returned value to a (Shape), since it is already a Shape. The cast is just cluttering your code. Similarly, the many casts in the 2nd example of your UPDATE 2 are making the code hard to read. I would prefer the first version, with two references (not pointers btw - Java has no pointers).

And I care only about code readability here - as others have already noted, you should really, really not waste your time thinking about the cost of casts. Just focus on making your code as simple and readable as possible. You would most likely never ever going to notice the tiniest bit of difference between the performance of the two code snippets you show above (unless maybe if they are executed in a tight loop millions of times - but then, I guess, the JIT would optimize the casts away anyway). However, you will notice the difference it takes in time to understand one code snippet versus the other, for someone who is new to this code - or someone who has forgotten the details already, which could be you in about 6 months.

Does converting a variable count as a primitive operation in Big O?

I believe that you're trying to get a mathematical formula of the number of primitive operations needed given an input to a method. Similar to what is done in the "Primitive Operations" section in https://www.cpp.edu/~ftang/courses/CS240/lectures/analysis.htm#primitive_operations

The answer is maybe. I would consider it a primitive operation because whether or not casting can happen first needs to be checked. For example, in java: Does Java casting introduce overhead? Why?

Why does Java ArrayList use per-element casting instead of per-array casting?

It's more complicated than that: generics are erased in byte code, and the erasure of T[] is Object[]. Likewise, the return value of get() becomes Object. To retain integrity of the type system, a checked cast is inserted when the class is actually used, i.e.

Integer i = list.get(0);

will be erased to

Integer i = (Integer) list.get(0);

That being the case, any type check within ArrayList is redundant. But it's really beside the point, because both (T) and (T[]) are unchecked casts, and incur no runtime overhead.

One could write a checked ArrayList that does:

T[] array = Array.newInstance(tClass, n);

This would prevent heap pollution, but at the price of a redundant type check (you can not suppress the synthentic cast in calling code). It would also require the caller to provide the ArrayList with the class object of the element type, which clutters its api and makes it harder to use in generic code.

Edit: Why is generic array creation forbidden?

One problem is that arrays are checked, while generics are unchecked. That is:

Object[] array = new String[1];
array[0] = 1; // throws ArrayStoreException

ArrayList list = new ArrayList<String>();
list.add(1); // causes heap pollution

Therefore, the component type of an array matters. I assume this is why the designers of the Java language require us to be explicit about which component type to use.



Related Topics



Leave a reply



Submit