How much processing and memory use does casting take in Java?
I am considering whether it is better to have two pointers, one for each object开发者_如何学JAVA sub class and super, or whether I should just use casting.
How much system resources does this use:
objectName.functionOne();
((SubClass) objectName).functionOther();
Is it better than:
SuperClass objectA = (SuperClass) getSameInstance();
SubClass objectB = getSameInstance();
objectA.functionOne();
objectB.functionOther();
Basically, my main question is about the resources used with casting, versus making an extra pointer. It seems like I could save several in line casts, such as:
((SubClass) objectName).functionOther();
However, is it worth it?
Thanks,
GraeUPDATE:
There were some unclear parts to my question. Basically, I have a super class that I am using through out a large function. It works with three subclasses. Some the super class is working as I would like. However, I hit a road block in a few places where I have to use a function from one of the three different subclass; a function that is only in one of the subclasses.
I could just have:
SuperClass instanceRef;
SubClass instanceRef2;
instanceRef.etc()
instanceRef.etc2()
instanceRef.etc3()
instanceRef2.specialSubClassOnlyCall();
instanceRef2.specialSubClassOnlyCall2();
or I could have:
SuperClass instanceRef;
instanceRef.etc()
instanceRef.etc2()
instanceRef.etc3()
((SpecialSubClass)instanceRef).specialSubClassOnlyCall();
((SpecialSubClass)instanceRef).specialSubClassOnlyCall2();
However, I don't know which is more efficient.
UPDATE 2:
Here is an example to show you what I am talking about:
class Shape
Triangle extends Shape
Square extends Shape
Circle extends Shape
Cube extends Shape
The Two Pointer Example: (Downside an extra pointer.)
Shape pointer1 = (Shape) getSomeRandomShape();
Cube pointer2 = null;
pointer1.getWidth();
pointer1.getHeight();
pointer1.generalShapeProp();
pointer1.generalShapeProp2();
pointer1.generalShapeProp3();
if(sure_its_cube)
{
pointer2 = (Cube) pointer1;
pointer2.getZAxis();
pointer2.getOtherCubeOnlyThing();
pointer2.getOtherCubeOnlyThing2();
pointer2.getOtherCubeOnlyThing3();
pointer2.getOtherCubeOnlyThing4();
}
Or I could do it this way. (Downside a bunch of casts.)
Shape pointer1 = (Shape) getSomeRandomShape();
pointer1.getWidth();
pointer1.getHeight();
pointer1.generalShapeProp();
pointer1.generalShapeProp2();
pointer1.generalShapeProp3();
if(sure_its_cube)
{
((Cube)pointer1).getZAxis();
((Cube)pointer1).getOtherCubeOnlyThing();
((Cube)pointer1).getOtherCubeOnlyThing2();
((Cube)pointer1).getOtherCubeOnlyThing3();
((Cube)pointer1).getOtherCubeOnlyThing4();
}
So is five casts worse than one extra pointer? What is it was six casts, or 20? Is one cast worse than the pointer.
Grae
Do whatever makes the code clearer, forget about micro-optimizations.
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.
Casting is not an "operation" that is done at runtime. It's just needed by the compiler to assure you static type safety.
Just looked at JVM code, the two approaches are basically equivalent, they are implemented as
CHECKCAST Main$B
INVOKEVIRTUAL Main$B.mySubMethod()V
so a small overhead is present, but it's the same in both cases (since you gotta do a downcast anyway).
Readability and code maintenance should be your priority in something like this, not performance, unless you actually hit a bottleneck (extremely unlikely).
However, there is no reason to have two references (pointers). Just reference the subclass. Anything you could do with the superclass reference you can do with the subclass reference, in almost all cases (a parameter to an overloaded method is the only exception I know of).
Just go with whichever solution is easier to read and cleanest to maintain (likely the first solution). At that low a level of optimization, it's really not worth it except in edge cases where you really need the extra 0.01% performance improvement.
For what it's worth, you don't actually need to cast a subclass to a superclass reference (second solution listed), only the other way around. When casting a superclass to a subclass, it's generally preferred verify its type with instanceof
prior to the cast rather than making assumptions.
Lets say you have a 64-bit machine and it saves 8-bytes of resources. Lets say you have spent 10 minutes think about it. Was it a good use of your time?
1 GB adds about $100 to the cost of a server so 8 bytes cost about $0.0000008
10 minutes of you time is worth about $1 on minimum wage.
The resource is reusable, your time is not. More importantly the time of anyone reading/ supporting your code is likely to be even more expensive and that is why simplicity/clarity is far more important.
精彩评论