为什么char []比String更好? - Java

时间:2011-11-18 23:42:50

标签: java string character

参考链接:File IO Tuning,标题为“进一步调整”的最后一节,作者建议使用char []来避免为文件中的n行生成String对象,我需要了解怎么做

char[] arr = new char{'a','u','t','h', 'o', 'r'}

不同

String s = "author"

在内存消耗或任何其他性能因素方面? String对象是否内部存储为字符数组?我觉得很傻,因为我以前从没想过这个。 : - )

5 个答案:

答案 0 :(得分:6)

在Oracle的JDK中,String有四个实例级字段:

  • 字符数组
  • 积分偏移量
  • 整数字符数
  • 整数散列值

这意味着每个String引入了一个额外的对象引用(String本身),以及除了字符数组本身之外的三个整数。 (偏移量和字符数允许在通过the String#substring() methods生成的String个实例之间共享字符数组,some other Java library implementers have eschewed的设计选择。)除了额外的存储成本之外,还有一个更多级别的访问间接,更不用说使用String保护其字符数组的边界检查。

如果你能够分配和消费基本的字符数组,那么就有空间可以保存。在Java中这样做当然不是惯用的;有理由提出明智的评论来证明这一选择的合理性,最好是提及已经分析差异的证据。

答案 1 :(得分:6)

在你所提到的例子中,这是因为只有一个单个字符数组被分配给整个循环。它反复读入同一个数组,并在适当的位置进行处理。

将其与使用readLine进行比较,后者需要在每次迭代时创建 String实例。每个String实例都会包含一些int字段以及对包含实际数据的char[]的引用 - 因此每次迭代需要两个新实例 。 / p>

我通常认为差异是微不足道的(与一个体面的GC非常有效地丢弃未使用的“年轻”对象)相比,读取数据所涉及的IO - 假设它来自磁盘 - 但我相信这就是作者试图制作。

答案 2 :(得分:2)

作者没有得到正确的理由。 in.readLine()中的实际开销是在创建一个String时复制char []缓冲区。在处理大数据时,额外的复制是最大的成本。

可以在JDK中对其进行优化,以便不需要额外的复制。

答案 3 :(得分:2)

有几个理由认为字符数组在Java中是比String更好的选择:

说存储密码

1)由于字符串在Java中是不可变的,如果您将密码存储为纯文本,它将在内存中可用,直到垃圾收集器清除它并且因为String在字符串池中使用对于可重用性,很有可能它会长时间保留在内存中,从而构成安全威胁。

由于任何有权访问内存转储的人都可以以明文形式找到密码,这是另一个原因,您应该始终使用加密密码而不是纯文本。

由于字符串是不可变的,因此无法更改字符串的内容,因为任何更改都会产生新的字符串,而如果您使用char [],您仍然可以将其所有元素设置为空白或零。因此,在字符数组中存储密码可以明显降低窃取密码的安全风险。

2)Java本身建议使用JPasswordField的getPassword()方法,它返回一个char []和不推荐使用的getText()方法,它以明文形式返回密码,说明安全原因。很好地遵循Java团队的建议并坚持标准而不是反对它。

3)使用String时,始终存在在日志文件或控制台中打印纯文本的风险,但如果使用Array,则不会打印数组的内容,而是打印其内存位置。虽然不是一个真正的原因,但仍然有意义。

对于这个简单的程序

String strPassword="Unknown";
char[] charPassword= new char[]{'U','n','k','n','o','w','n'};
System.out.println("String password: " + strPassword);
System.out.println("Character password: " + charPassword);

输出:

String password: Unknown
Character password: [C@110b053

这就是为什么字符数组比用于在Java中存储密码的String更好的选择。虽然使用char []还不够,但您需要擦除内容才能更安全。

希望这会有所帮助。

答案 4 :(得分:1)

我的答案将集中在这个类似的线上的其他堆栈问题,其他人已经发布了更直接的答案。

other questions类似于此,建议似乎与使用StringBuilder有关。

如果您关注字符串集中,请查看performance as described here between three different implementations。使用another stack post可以为您提供一些额外的指示和示例,您可以尝试自己查看性能。