6

私には子クラスがあり、それぞれが他のメンバーと一緒に異なるタイプの価値を持っています。LongObject、IntObject、StringObjectなどが存在する可能性があります。

long、int、stringなどの値が与えられ、それぞれLongObject、IntObject、StringObjectなどを作成する必要があります。

以下に示すようにメソッドをオーバーロードする方が速いでしょうか(a)、または以下に示すようにelseifを使用するだけですか(b)?

目立ったパフォーマンスの違いではない場合があります。とにかく、オーバーロードされたメソッドはif/elseと同様の方法で実装されている可能性があります。知らない。

ただテストするように言っている人もいます。確かに、私はすべきです。また、誰かが知っているなら、このタイプのオーバーロードが内部でどのように処理されるかを知りたいです。

ご意見をお聞かせください。

ありがとう、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);
    ...
}

編集:私はすべての詳細を完全に追加しなかったと思います、あなたの何人かはそれを捕まえました。どちらの選択肢でも、オブジェクト/値を取得し、その値からそれがどのタイプであるかを判断する必要があります。したがって、オーバーロードされたメソッドを使用するためにも、何らかのif/elseを実行する必要があります。

4

7 に答える 7

24

ここには大きな矛盾があります。オーバーロードはコンパイル時に選択されますが、「if(値が長い)」は実行時のテストになります。

コンパイル時にタイプがわかっている場合は、その情報を使用することを強くお勧めします。そうしないと、とにかくオーバーロードオプションは実際には実行可能ではありません。

編集:コメントは、コンパイル時に選択されるオーバーロードについて少し詳しく説明することを示唆しています。

コンパイラは、引数に関するコンパイル時の情報に基づいて、呼び出されるメソッドシグネチャを選択します。これは、使用するメソッドの実装がメソッドの実際のターゲットのタイプによって決定されるオーバーライドとは異なります。

次に例を示します。

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)

于 2009-04-16T21:57:27.027 に答える
6

オーバーロードソリューションは、コンパイル時に解決されるため、はるかに高速です(そしてより優れています)。

基本的に、コンパイラは、値を渡すときに呼び出すメソッドを判断します。getObject( "abc")を呼び出すと、コンパイラはメソッドへの呼び出しを発行します。

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

if ... else状態を調べて、実行時にオブジェクトタイプ(低速のアクティビティ)を評価しようとするのではなく。

于 2009-04-16T22:01:04.193 に答える
1

条件が1秒間に何百万回もテストされない限り、心配する必要はありません。

于 2009-04-16T22:20:13.430 に答える
0

a)(オーバーロード)は、ジャストインタイムコンパイラに最適化の機会を与えるため、より高速になります。新しいオブジェクトの作成をインライン化することを決定できます。

于 2009-04-16T22:02:31.523 に答える
0

実行時に型情報を評価する必要があるときはいつでも、比較的遅い操作になりがちです。選択肢がある場合は、ほとんどの場合、コンパイル時にそうするコードを作成することをお勧めします。

これは、「アーリーバインディング」と「レイトバインディング」と呼ばれることがよくあります。

于 2009-04-16T22:15:58.650 に答える
0

カスケード条件文は、オブジェクト指向プログラミングでは悪いカルマであり、オブジェクトの型をテストするときは本当に醜いです。言語はすでにそのテストの王様にポリモーフィズムを提供しています。

また、Java以外の人として、私は、、を使用getLong(l)getInt(i)ますgetString(s)。私はメソッドのオーバーロードがそうでないよりも混乱していると思います(imho静的型はプログラムの実行に影響を与えるべきではありません(最適化に関して(そして外見にもかかわらず私はLisperではありません:))))

于 2009-04-16T22:57:40.830 に答える
0

最も重要なことは、getObj(int)、getObj(string)など-予期しないものを渡そうとすると、コンパイル時に失敗することです。

オブジェクトをメソッドに渡すことを許可すると、アプリがメソッドで処理できないものを渡そうとし、醜いランタイムエラーが発生する可能性があります。

于 2009-04-16T23:18:07.457 に答える