Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java (字符串)或.toString()?_Java_Casting - Fatal编程技术网

Java (字符串)或.toString()?

Java (字符串)或.toString()?,java,casting,Java,Casting,我有一个带有对象o参数的方法 在这个方法中,我确切地知道在“o”中有一个非空的字符串。不需要检查,也不需要做其他事情。我必须像对待字符串一样对待它 只是好奇-什么更便宜-将其转换为String,或者使用Object.toString()? 或者时间-/cpu-/mem-价格是否相同 更新: 该方法接受对象,因为它是接口的实现。无法更改参数类型 而且它不能是空的。我只是想说,我不需要检查它是否为空。在我的例子中,总是有一个非空字符串。在o中不能有一个空字符串。如果o为null,则它不包含null字

我有一个带有
对象o
参数的方法

在这个方法中,我确切地知道在“o”中有一个非空的
字符串。不需要检查,也不需要做其他事情。我必须像对待字符串一样对待它

只是好奇-什么更便宜-将其转换为
String
,或者使用
Object.toString()
? 或者时间-/cpu-/mem-价格是否相同

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


而且它不能是空的。我只是想说,我不需要检查它是否为空。在我的例子中,总是有一个非空字符串。

在o中不能有一个空字符串。如果o为null,则它不包含null字符串,它只是null。首先检查o是否为空。如果您在null上强制转换或调用ToString(),您将崩溃。

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


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

我不会太在意性能,如果此操作每秒执行几千次,则没有明显区别

然而,我担心的是“知道”输入。您有一个方法可以接受一个
对象
,您应该这样对待它,也就是说,您不应该知道关于参数的任何信息,除了它依附于
对象
接口之外,该接口恰好有一个
toString()
方法。在这种情况下,我强烈建议使用这种方法,而不是仅仅假设任何事情


OTOH,如果输入总是
String
null
,只需将方法更改为接受
String
s,并显式检查
null
s(在处理非原语时无论如何都应该这样做…

我将使用强制转换。这验证了您的“知识”,即它是一个字符串。无论出于何种原因,如果您最终出现了一个bug,而有人传入了字符串以外的内容,我认为抛出一个异常(强制转换可以做到这一点)比继续使用有缺陷的数据执行要好。

强制转换到字符串更便宜,因为它不需要外部函数调用,只是内部类型检查。

如果“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(o == null)
    {
        throw new IllegalArgumentException("o cannot be null");
    }

    str = o.toString();
}

奇怪的是,我发现强制转换比tostring调用隐含的vtable查找慢。

假设引用类型是一个对象,并且所有对象都有一个tostring(),只需调用Object.tostring()。toString.toString()只返回这个值

  • toString()的代码类型较少
  • toString()的字节码更少
  • 与多态调用相比,强制转换是一项昂贵的操作
  • 演员阵容可能会失败
  • 使用String.valueOf(object),如果object.toString()不为null,则只调用它
根据

最后,结果令人惊讶 清除:速度至少是原来的两倍 将对象强制转换为字符串而不是调用 Object.toString()


我说我的问题没有什么价值:)我只是好奇什么理论上更便宜。但是无论如何,代价将取决于虚拟机在虚拟方法调用和类型检查方面的效率。这是特定于实现的。您在多个JRE中测试过它吗?我在.NET中看到了令人惊讶的结果。实际上,我怀疑性能在现实生活中是否会起作用,但从防御性编码的角度来看,强制转换更好。方法调用应该内联。使用泛型删除(显式)强制转换将是最好的。@Jon Skeet:我同意性能上的差异不会太大@Tom Hawtin:由于在编译时不知道要接收的对象的类型,所以我看不出方法调用是如何内联的。你能澄清一下吗?@euphoria83:由JIT编译器内联,而不是由javac内联。事实上,不,方法不能内联。类型仅已知为对象,实际实现取决于运行时类型。哪一个更快仍然取决于实现,但据我记忆所及(实际上我曾经用microbenchmark测试过),强制转换似乎更快。这并不是一个显而易见的答案:类型检查并不总是更快。对于字符串类型,它可以是,因为它是一个对象(不是接口),并且是最后一个对象。强制转换null不会崩溃。它甚至不会抛出NullPointerException,它只会对新类型调用null。:)前两个代码片段不会真正编译(
final
变量可能尚未初始化)。您需要一个
else
,它要么抛出异常,要么初始化
str
到某个对象。在.NET世界中,我们测量了它,而ToString()更快。考虑到这种情况的原因,jittingjvm几乎肯定也是如此。这对我来说是正确的答案。为什么?因为强制转换
(string)Registry.GetValue…
会引发尝试强制转换Int32对象的异常,而
Registry.GetValue…ToString()
会按预期工作。我现在运行了该代码,差异可以忽略不计(Mac,Java 8)
void foo(final Object o)
{
    final String str;

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

    str = o.toString();
}