(文字列)または.toString()?


89

Object oパラメータ付きのメソッドがあります。

この方法では、Stringnullではない「o」が含まれていることを正確に知っています。確認したり、他のことをしたりする必要はありません。私はそれをStringオブジェクトとまったく同じように扱わなければなりません。

ただ好奇心が強い-何が安いか-それをキャストStringするObject.toString()か、使用しますか?それとも時間-/ cpu- / mem-価格で同じですか?

更新:このメソッドはObject、インターフェースの実装であるため、受け入れます。パラメータタイプを変更する方法はありません。

そして、それはまったくあり得ませんnull。nullや空をチェックする必要はないと言いたかっただけです。私の場合、常に空でない文字列があります。


1
.NETの世界では、それを測定しましたが、ToString()の方が高速です。これがそうである理由を考えると、同じことがほぼ確実にJVMのジッティングにも当てはまります。
ジョシュア

回答:


72

文字列へのキャストは、外部関数呼び出しを必要とせず、内部型チェックのみを必要とするため、より安価です。


4
複数のJREでテストしましたか?.NETでこの状況を正確に表すと、驚くべき結果が得られました。現実的には、パフォーマンスが実際の生活で重要になるとは思えませんが、防御的なコーディングの観点からはキャストの方が優れています。
Jon Skeet

メソッド呼び出しはインライン化する必要があります。ジェネリックを使用して(明示的な)キャストを削除するのが最善です。
トムホーティン-タックライン2009年

@Jon Skeet:パフォーマンスの違いはそれほど大きくないことに同意します。@Tom Hawtin:コンパイル時に受信されるオブジェクトのタイプがわからないため、メソッド呼び出しをインライン化する方法がわかりません。plzで明確にできますか?
euphoria83

@ euphoria83:javacではなく、JITコンパイラによってインライン化されます。
MichaelMyers

実際には、いいえ、メソッドをインライン化することはできません。タイプはオブジェクトとしてのみ認識されており、実際の実装はランタイムタイプによって異なります。どちらが速いかはまだ実装に依存しますが、私が覚えている限り(私は実際にある時点でマイクロベンチマークでテストしました)、キャストはより速いようです。これは明白な答えではありません。型チェックは必ずしも高速ではありません。文字列型の場合、それはオブジェクト(インターフェイスではない)であり、最後のオブジェクトである可能性があります。
StaxMan 2009年

45

ギプスを使います。これは、文字列であるという「知識」を検証します。なんらかの理由でバグが発生し、誰かが文字列以外のものを渡した場合、欠陥のあるデータで実行を続けるよりも、例外をスローする方がよいと思います(キャストはこれを行います)。



7

オブジェクトoが文字列であることがわかっている場合は、それを文字列にキャストして、そのように強制します。文字列であることが確実にわかっているオブジェクトでtoString()を呼び出すと、混乱が生じる可能性があります。

オブジェクトoが文字列以外の場合は、toString()を呼び出す必要があります。


これは私にとって正しい答えです。どうして?鋳造が原因(string)Registry.GetValue...のに対し、のInt32オブジェクトをキャストしようとしているため、例外をスローRegistry.GetValue...ToString()期待通りに動作します。
重力

3

この操作が1秒間に数千回でも実行されれば、パフォーマンスにはあまり関心がありません。具体的な違いはありません。

しかし、私は入力を「知る」ことに関心があります。を受け入れるメソッドがあり、Objectそれをそのように扱う必要があります。つまり、メソッドを持っているインターフェイスに準拠していることを除いて、パラメータについて何も知らないはず です。この場合、何かを想定するのではなく、その方法を使用することを強くお勧めします。ObjecttoString()

OTOH、入力がある場合は、必ずどちらか Stringまたはnull単に受け入れるようにする方法を変更する、StringSを、そしてに対して明示的に確認してくださいnull(...非プリミティブを扱うたびに、とにかくやるべき)■


私の質問には価値のある意味はないと言いました:)理論的に何が安いのか興味があります。しかしとにかく
感謝し

コストは、仮想メソッド呼び出しと型チェックでのVMの効率によって異なります。これは実装固有です。
Jon Skeet

2

参照型がオブジェクトであり、すべてのオブジェクトにtoString()がある場合、object.toString()を呼び出すだけです。String.toString()はこれを返すだけです。

  • toString()は、入力するコードが少なくなります。
  • toString()はバイトコードが少ないです。
  • キャストは、ポリモーフィック呼び出しと比較してコストのかかる操作です。
  • キャストが失敗する可能性があります。
  • nullでない場合はobject.toString()を呼び出すだけのString.valueOf(object)を使用します。

1

「o」にあるものが文字列である場合、大きな違いはありません(キャストの方が速い可能性がありますが、それはVM /ライブラリの実装です)。

「o」が文字列ではない可能性があるが、文字列であると想定される場合、キャストは必要なものです(ただし、メソッドにオブジェクトではなく文字列を使用させる必要があります)。

「o」が任意のタイプである可能性がある場合は、toStringを使用する必要がありますが、最初にnullを確認してください。

void foo(final Object o)
{
    final String str;

    // without this you would get a class cast exception
    // be wary of using instanceof though - it is usually the wrong thing to do
    if(o instanceof String)
    {
        str = (String)o;
    }    
}

または

void foo(final Object o)
{
    final String str;

    // if you are 100% sure that o is not null then you can get rid of the else
    if(o != null)
    {
        str = o.toString();
    }
}

私はむしろ最後のものを次のようにコーディングしたいと思います:

void foo(final Object o)
{
    final String str;

    if(o == null)
    {
        throw new IllegalArgumentException("o cannot be null");
    }

    str = o.toString();
}

最初の2つのスニペットは実際にはコンパイルされません(final変数が初期化されていない可能性があります)。else例外をスローするか、str何かに初期化するものが必要です。
ブルーノ・レイス

1

奇妙なことに、キャストはtostring呼び出しによって暗示されるvtableルックアップよりも遅いことがわかりました。


1

'o'にnull文字列を含めることはできません。oがnullの場合、null文字列は含まれず、単にnullになります。最初にoでnullを確認してください。nullでToString()をキャストまたは呼び出すと、クラッシュします。


2
nullをキャストしてもクラッシュしません。NullPointerExceptionをスローすることすらなく、新しい型に対してnullを呼び出すだけです。:)
ボンベ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.