(String) veya .toString ()?


89

Object oParametreli bir yöntemim var .

Bu yöntemde, Stringnull olmayan bir "o" nun olduğunu tam olarak biliyorum . Kontrol etmeye veya başka bir şey yapmaya gerek yoktur. Ona tam olarak bir Stringnesne gibi davranmalıyım .

Sadece merak ediyorum - daha ucuz olanı - yayınlamak mı Stringyoksa kullanmak Object.toString()mı? Yoksa zaman / cpu- / mem- fiyatına göre aynı mı?

Güncelleme: Yöntem Object, bir arayüzün uygulaması olduğu için kabul eder . Parametre türünü değiştirmenin bir yolu yoktur.

Ve hiç olamaz null. Sadece boş ya da boş olup olmadığını kontrol etmem gerektiğini söylemek istedim. Benim durumumda her zaman boş olmayan bir dize vardır.


1
.NET dünyasında bunu ölçtük ve ToString () daha hızlı. Bunun neden böyle olduğu düşünüldüğünde, aynı şey neredeyse kesin bir JVM için de geçerlidir.
Joshua

Yanıtlar:


73

String'e çevrim daha ucuzdur çünkü bu harici bir fonksiyon çağrısı gerektirmez, sadece dahili tip kontrolü gerektirir.


4
Birden fazla JRE'de test ettiniz mi? NET'te bu durum için şaşırtıcı sonuçlar gördüm. Gerçekçi olarak, performansın gerçek hayatta önemli olacağından şüpheliyim - ancak oyuncu seçimi, savunma kodlama açısından daha iyidir.
Jon Skeet

Yöntem çağrısı satır içi olmalıdır. (Açık) kastı kaldırmak için jenerik kullanmak en iyisidir.
Tom Hawtin - tackline

@Jon Skeet: Performans farkının fazla olmayacağına katılıyorum. @Tom Hawtin: Alınacak nesnenin türü derleme zamanında bilinmediğinden, yöntem çağrısının nasıl satır içine alınacağını göremiyorum. Lütfen açıklayabilir misin?
euphoria83

@ euphoria83: javac tarafından değil, JIT derleyicisi tarafından satır içine alınmıştır.
Michael Myers

Aslında hayır, yöntem satır içi olamaz. Tür yalnızca Nesne olarak bilinir ve gerçek uygulama çalışma zamanı türüne bağlıdır. Hangisinin daha hızlı olduğu hala uygulamaya bağlıdır, ancak hatırladığım kadarıyla (aslında bir noktada microbenchmark ile test ettim), döküm daha hızlı görünüyor. Bu açık bir cevap değildir, çünkü tür denetimi her zaman daha hızlı değildir. String tipi için bir nesne (arayüz değil) olduğu için olabilir ve bunda sonuncusu olabilir.
StaxMan

45

Bir alçı kullanırdım. Bu, bir dizge olduğuna dair "bilginizi" doğrular. Herhangi bir nedenle bir hata ile karşılaşırsanız ve birisi bir dizeden başka bir şey aktarırsa, hatalı verilerle çalışmaya devam etmektense bir istisna (bir dökümün yapacağı gibi) atmanın daha iyi olacağını düşünüyorum.



7

Eğer Object o'nun bir String olduğunu biliyorsanız, sadece onu bir String'e çevirin ve bu şekilde uygulayın derim. String olduğundan emin olduğunuz bir nesnede toString () 'i çağırmak sadece kafa karışıklığı yaratabilir.

Object o, String dışında herhangi bir şey olabilirse, toString () öğesini çağırmanız gerekir.


Bu benim için doğru cevap. Neden? Çünkü çevrim (string)Registry.GetValue..., bir Int32 nesnesini atmaya çalışmak için bir istisna atarken Registry.GetValue...ToString()beklendiği gibi çalışır.
yerçekimi

3

Bu işlem saniyede sadece birkaç bin kez yapılsa bile performans beni çok endişelendirmez - somut bir fark yoktur.

Bununla birlikte, girdiyi "bilmek" ile ilgilenirim. An'ı kabul eden bir yönteminiz var Objectve ona bu şekilde davranmalısınız, yani bir yönteme sahip olan arayüze bağlı olması dışında parametre hakkında hiçbir şey bilmemelisiniz . Bu durumda, herhangi bir şey varsaymak yerine bu yöntemi kullanmanızı şiddetle öneririm.ObjecttoString()

OTOH, eğer giriş her zaman ya Stringda ise null, sadece yöntemi Strings kabul edecek şekilde değiştirin ve s için açıkça kontrol edin null(ilkel olmayanlarla uğraşırken her durumda yapmanız gerekir ...)


Sorumun değerli bir anlamı olmadığını söyledim :) Sadece teorik olarak neyin daha ucuz olduğunu merak ediyorum . Ama yine de
teşekkürler

Maliyet, VM'nin sanal yöntem çağrılarında ve tür kontrolünde ne kadar verimli olduğuna bağlı olacaktır. Bu uygulamaya özgüdür.
Jon Skeet

2

Başvuru türünün bir Object olduğu ve tüm Nesnelerin bir toString () öğesine sahip olduğu göz önüne alındığında, yalnızca object.toString () öğesini çağırın. String.toString () yalnızca bunu döndürür.

  • toString (), yazılacak daha az koddur.
  • toString () daha az bayt kodudur.
  • döküm, polimorfik çağrıya karşı pahalı bir işlemdir.
  • oyuncu kadrosu başarısız olabilir.
  • Boş değilse, yalnızca object.toString () öğesini çağıran String.valueOf (nesne) kullanın.

1

Eğer "o" da sahip olduğunuz şey bir String ise, o zaman pek bir fark yoktur (büyük olasılıkla cast daha hızlıdır, ancak bu bir VM / Library uygulamasıdır).

Eğer "o" bir Dize olmayabilir, ancak bir Dize olması gerekiyorsa, istediğiniz şeydir (ancak yöntemin bir Nesne yerine bir Dize almasını sağlamalısınız).

Eğer "o" herhangi bir türde olabiliyorsa, toString'i kullanmanız gerekir - ancak önce null değerini kontrol ettiğinizden emin olun.

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

veya

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

Sonuncuyu şu şekilde kodlamayı tercih ederim:

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

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

    str = o.toString();
}

İlk 2 parçacık gerçekten derlenmeyecektir ( finaldeğişken başlatılmamış olabilir). elseYa bir istisna atacak ya da bir şeyi başlatacak bir strşeye ihtiyacınız var.
Bruno Reis

1

Tuhaf bir şekilde, oyuncunun tostring çağrısının ima ettiği vtable aramasından daha yavaş olduğunu buldum.


1

'O'da boş dizge olamaz. O null ise, boş bir dizge içermez, sadece boştur. Önce o null değerini kontrol edin. Eğer varsa döküm boş veya çağrı ToString () o zaman kaza yapar.


2
Boş döküm çökmeyecek. Bir NullPointerException bile atmaz, sadece yeni türe null çağırır. :)
Bombe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.