(字符串)还是.toString()?


89

我有一个带有Object o参数的方法。

在这种方法中,我完全知道String在“ o”中存在一个不为空的值。无需检查或执行其他操作。我必须像对待String对象一样对待它。

只是好奇-更便宜的是-将其投放String或使用Object.toString()?还是按时间/ CPU /内存价格相同?

更新:该方法可以接受,Object因为它是接口的实现。无法更改参数类型。

而且根本不可能null。我只是想说我不需要检查它是否为空或为空。就我而言,总是有一个非空字符串。


1
在.NET世界中,我们对其进行了测量,并且ToString()更快。考虑到这种情况的原因,jitting JVM几乎同样如此。
约书亚2014年

Answers:


72

强制转换为String较为便宜,因为它不需要外部函数调用,只需内部类型检查即可。


4
您是否已在多个JRE中对其进行了测试?在.NET中消除这种情况的效果令人惊讶。实际上,我怀疑性能在现实生活中会很重要-但从防御性编码的角度来看,转换效果更好。
乔恩·斯基特

方法调用应该内联。使用泛型删除(显式)强制转换将是最好的。
Tom Hawtin-抢险活动

@Jon Skeet:我同意性能差异不会太大。@Tom Hawtin:由于在编译时不知道将要接收的对象的类型,因此我看不到如何内联方法调用。你能澄清一下吗?
euphoria83

@ euphoria83:由JIT编译器而不是javac内联。
迈克尔·迈尔斯

实际上,不,方法不能内联。类型仅是对象,实际实现取决于运行时类型。哪一个速度更快仍取决于实现方式,但据我所知(实际上我曾经在一点上用微基准测试过它),投射似乎更快。这不是一个显而易见的答案:类型检查并不总是更快。对于String类型,可以是因为它是一个对象(不是接口),而在那是最后一个。
StaxMan

45

我会使用演员表。验证您的“知识”是一个字符串。如果由于某种原因而导致错误,并且有人传递了除字符串以外的其他东西,我认为抛出异常(强制转换会成功)比继续对有缺陷的数据执行会更好。



7

如果您知道对象o是一个字符串,我想说就是将其转换为字符串并以这种方式强制执行。在您确定是String的对象上调用toString()可能只会增加混乱。

如果对象o可能不是字符串,则需要调用toString()。


这是我的正确答案。为什么?因为强制类型转换(string)Registry.GetValue...尝试抛出一个Int32对象会引发异常,而Registry.GetValue...ToString()按预期方式工作。
重力

3

我不会太担心性能,如果此操作每秒仅执行数千次,则没有明显的区别。

但是,我会担心“知道”输入。你必须接受的一个方法Object,你应该把它当作这样的,即你不应该 知道的有关参数任何东西,除了它遵循的Object接口,这恰好有一个toString()方法。在这种情况下,我强烈建议您使用该方法,而不是仅仅假设任何事情。

OTOH,如果输入始终Stringnull,则只需将方法更改为接受Strings,并显式检查nulls(无论何时使用非基元,都应执行此操作……)


我说过我的问题没有任何有价值的意义:)我只是想知道理论上更便宜的东西。但是无论如何
Vugluskr

成本将取决于VM在虚拟方法调用与类型检查之间的效率。那是特定于实现的。
乔恩·斯基特

2

假设引用类型是一个对象,并且所有对象都有一个toString(),只需调用object.toString()即可。String.toString()仅返回此值。

  • toString()是较少键入的代码。
  • toString()少了字节码。
  • 强制转换是一个昂贵的操作,而一个多态调用。
  • 演员可能会失败。
  • 使用String.valueOf(object),如果它不为null,它将仅调用object.toString()。

1

如果“ o”中的内容是字符串,则没有太大区别(可能强制转换更快,但这是VM / Library实现的事情)。

如果“ 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中的空字符串”。如果o为null,则不包含null字符串,而仅为null。只需先检查o是否为null。如果你上null或调用toString(),你会崩溃。


2
强制为null不会崩溃。它甚至不会抛出NullPointerException,它只会将null调用新类型。:)
孟买
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.