views:

611

answers:

8

Hi all,

I have child classes, each carries a different type of value along with other members. There may be a LongObject, IntObject, StringObject, etc.

I will be given a value, which can be a long, int, string, etc., and I have to create a LongObject, IntObject, StringObject, etc., respectively.

Would it be faster to overload a method as shown below (a) or just use a elseif as shown below (b)?

It may not be a noticeable performance difference. It may be that the overloaded methods are implemented in a similar manner to the if/else anyway. I don't know.

I can also hear some of you saying to just test it. Sure, I ought to. I would also like to know how this type of overloading is handled under the hood, if anyone knows.

Please let me know what you think.

Thanks, jbu

a)

BaseObject getObject(long l)
{
     return new LongObject(l);
}

BaseObject getObject(int i)
{
     return new IntObject(i);
}

BaseObject getObject(String s)
{
     return new StringObject(s);
}

...

b)

BaseObject getObject(Object x)
{
    if(value is a long)
         return new LongObject((Long)x);
    else if(value is an int)
         return new IntObject((Int)x);
    else if(value is a String)
         return new StringObject((String)x);
    ...
}

edit: I guess I didn't completely add all the details, some of you caught it. For both choices, I still have to get an object/value and from the value determine what type it is. Therefore, I still have to do an if/else of some sort to even use the overloaded methods.

+17  A: 

There's a massive discrepancy here: overloads are chosen at compile-time whereas your "if (value is a long)" would be an execution-time test.

If you know the type at compile-time, I strongly suggest you use that information. If you don't, then the overloading option isn't really feasible anyway.

EDIT: The comment suggests I elaborate a bit about overloads being chosen at compile-time.

The compiler picks which method signature is called based on compile-time information about the arguments. This is unlike overriding where the method implementation to use is determined by the type of the actual target of the method.

Here's an example:

public class Test
{
    public static void main(String[] args)
    {
        Object x = "I'm a string";
        foo(x);
    }

    public static void foo(String x)
    {
        System.out.println("foo(String)");
    }

    public static void foo(Object x)
    {
        System.out.println("foo(Object)");
    }
}

This prints foo(Object) because the compile-time type of x is Object, not String. The fact that the execution-time type of the object that x refers to is String doesn't mean that foo(String) is called.

Jon Skeet
I am not sure what you mean by "overloads are chosen at compile-time." Could you please elaborate? I see that the methods are compiled at compile time (...) but the calls to those methods may not be. Am I missing something?
jbu
Oh I see the logic behind your statement. You're saying I'm going to need an if/else statement to decide which overloaded method to use. If I'm going to get an Object of unknown type, I will need to if/else it to cast it before I Use the overloaded method. Is that right?
jbu
@jbu: yes, I believe you understand it now.
rmeador
Yes - bit too late for my edit though ;)
Jon Skeet
Thanks, it helped me understand what was going on under the hood.
jbu
+5  A: 

The overloading solution is much faster (and better) because it is resolved at compile time.

Basically the compiler figure out which method to invoke when you pass a value to it. When you call getObject("abc"), the compiler will emit calls to method:

BaseObject getObject(String s)
{
     return new StringObject(s);
}

rather than trying to go through your if ... else state and evaluate the object type (which is a slow activity) at run time.

oykuo
A: 

a) (overloading) will be faster as it gives the just in time compiler a chance to optimize. It could decide to inline the new object creation.

Steve Kuo
+1  A: 

Just create a test and answer yourself.

stepancheg
A: 

Any time you have to evaluate type information at run-time, it's liable to be a relatively slow operation. When you have a choice, it's nearly always preferable to write code that does so at compile time.

This is often referred to as "early binding" versus "late binding."

Jekke
+1  A: 

Dont worry about, unless the condition is tested millions of times a second it doesnt matter.

mP
A: 

Cascading conditionals is bad karma in OO programming, and really ugly when testing the type of an object. The language already provides that king of test, with polymorphism.

Also, as a non-java guy, I'd use getLong(l), getInt(i), getString(s). I find method overloading more confusing than not (imho static types shouldn't influence the program execution (other than optimization-wise (and despite appearances I'm not a Lisper :) )))

Damien Pollet
A: 

Most importantly, getObj(int), getObj(string), etc. - will fail at compile time, if you try to pass something not expected.

If you allow any object to be passed into the method, you might have an instance where the app tries to pass in something that the method can't deal with, and you wind up with an ugly runtime error.

David