Java:重载和if / else哪个更快

7
我有子类,每个子类都携带着不同类型的值以及其他成员。可能会有LongObject、IntObject、StringObject等。
我将得到一个值,它可以是long、int、string等,然后我需要分别创建LongObject、IntObject、StringObject等。
使用下面所示的方法重载(a)还是只使用elseif(b)会更快呢?
这可能不会有明显的性能差异。这可能是因为重载的方法与if/else实现方式类似。我不知道。
我也听到一些人说要测试一下。当然,我应该测试一下。如果有人知道这种重载是如何处理的,请告诉我。
请让我知道你的想法。
谢谢, jbu
b)
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);
    ...
}

编辑:我想我没有完全添加所有细节,你们中的一些人抓住了它。 对于这两个选择,我仍然必须获取一个对象/值,并从该值确定它是什么类型。 因此,我仍然必须进行某种if / else判断才能使用重载方法。


我对于这类问题的个人哲学是:测试时间!运行数百万次迭代,然后看看哪个需要更长时间。 - cobbal
1
我知道会有人这么说 :) - jbu
只需创建一个测试并回答自己。 - stepancheg
7个回答

25

这里存在一个巨大的矛盾:重载是在编译时选择的,而您的 "if (value is a long)" 则是在执行时进行测试。

如果您在编译时知道类型,我强烈建议您使用该信息。如果不知道,则重载选项基本上是不可行的。

编辑:评论建议我稍微解释一下重载是如何在编译时选择的。

编译器根据有关参数的编译时信息选择要调用哪个方法签名。这与覆盖不同,在覆盖中,要使用的方法实现是由方法的实际目标类型确定的。

以下是一个示例:

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)");
    }
}

这会打印出 foo(Object),因为x的编译时类型是Object,而不是Stringx引用的对象的执行时类型为String并不意味着会调用foo(String)


我不确定你所说的“重载在编译时选择”的意思。能否请您详细解释一下?我知道方法是在编译时被编译的,但对这些方法的调用可能不是。我有什么遗漏吗? - jbu
哦,我明白你陈述的逻辑了。你是说我需要一个if/else语句来决定使用哪个重载方法。如果我要获取一个未知类型的对象,在使用重载方法之前,我需要用if/else进行强制转换。是这样吗? - jbu
@jbu:是的,我相信你现在明白了。 - rmeador
谢谢,这帮助我理解了引擎内部的运作。 - jbu

7

方法重载的解决方案更快(也更好),因为它在编译时就已经被解决了。

基本上,编译器会在你向其传递值时找出要调用的方法。当你调用getObject("abc")时,编译器将发出对以下方法的调用:

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

与其在运行时尝试通过 if ... else 语句并评估对象类型(这是一项缓慢的活动),不如采用其他方法。


1

不用担心,除非条件被测试了数百万次每秒,否则这并不重要。


0

a) (overloading) 会更快,因为它给了即时编译器一个优化的机会。它可以决定将新对象创建内联。


0

任何时候在运行时评估类型信息,都可能是一个相对较慢的操作。如果有选择的话,编写在编译时执行此操作的代码几乎总是更可取的。

这通常被称为“早期绑定”与“晚期绑定”。


0
级联条件语句在面向对象编程中很糟糕,当测试对象类型时会非常丑陋。语言已经提供了多态的测试方法。
此外,作为一个非Java程序员,我会使用 `getLong(l)`, `getInt(i)`, `getString(s)`。 我发现方法重载比不用更令人困惑(我认为静态类型不应影响程序执行(除了优化方面(尽管看起来我不是Lisper :)))。

0

最重要的是,getObj(int),getObj(string)等方法 - 如果您尝试传递意外的参数,将在编译时失败。

如果允许任何对象传递到方法中,您可能会遇到这样一种情况:应用程序尝试传递某些方法无法处理的内容,从而导致不美观的运行时错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接