是否将字符串封装为byte []以节省内存过量? (JAVA)

时间:2010-07-29 22:12:11

标签: java string oop memory-management byte

最近正在审查一些Java Swing代码并看到了这个:

byte[] fooReference;

String getFoo() {
   returns new String(fooReference); 
}

void setFoo(String foo) {
  this.fooReference = foo.getBytes();
}

以上内容可以节省你的记忆足迹,所以我被告知。

这种矫枉过正的是其他人以这种方式封装他们的字符串吗?

8 个答案:

答案 0 :(得分:31)

这是真的,真的坏主意。不要使用平台默认编码。没有什么可说的,如果你打电话给setFoo然后再getFoo,你就会收到相同的数据。

如果必须做类似的事情,那么使用UTF-8可以代表整个Unicode ......但我真的不会这样做。 可能可以节省一些内存,但代价是在大多数情况下不必要地执行转换 - 并且在未能使用适当的编码方面容易出错。

我敢说某些应用程序是合适的,但对于99.99%的应用程序来说,这是一个糟糕的主意。

答案 1 :(得分:10)

这不是很有用:
1.每次调用getFoo或setFoo时都会复制字符串,因此会增加CPU和内存使用量 这太模糊了

答案 2 :(得分:5)

一点历史性的游览......

如果你可以确定你永远不需要ISO-8859-1之外的任何东西,那么在Java(1.0 / 1.1)的早期使用字节数组而不是String对象实际上具有一些相当大的优势。使用当时的VM,与drawString()相比,使用drawBytes()的速度快10倍以上,实际上它确实节省了当时仍然非常稀缺的内存,并且applet曾经拥有32的硬编码内存屏障以后64 MB。不仅字节[]小于String对象的嵌入字符[],而且还可以保存相对较重的String对象本身,如果你有很多短字符串,这确实会产生很大的不同。除了访问普通字节数组也比使用String的访问器方法及其所有额外边界检查更快。

但是由于drawBytes在Java 1.2中不再快,因为当前的JIT比当时的Symantec JIT要好得多,所以byte []数组对字符串的剩余最小性能优势不再值得麻烦。记忆优势仍然存在,因此在一些非常罕见的极端场景中仍然可能是一种选择,但现在如果不是真的有必要,那就不应该考虑。

答案 3 :(得分:3)

它可能有点过分,甚至可能消耗更多内存,因为你现在有两个字符串副本。实际字符串的生存时间取决于客户端,但与许多此类黑客一样,它有点像过早优化。

答案 4 :(得分:3)

如果您预计会有很多相同的字符串,那么使用String.intern()方法可以节省内存的另一种更好的方法。

答案 5 :(得分:2)

每次调用getFoo()都会实例化一个新的String。这节省的记忆怎么样?如果您为垃圾收集器添加额外开销,以便在这些新引用变为未引用时清理这些新实例

答案 6 :(得分:2)

这确实没有任何意义。如果它是一个编译时常量,你不需要按回String,那么它会使更有意义。你仍然有字符编码问题。

如果它是char[]常数,那对我来说会更有意义。在现实世界中,有几个JSP编译器将字符串常量优化为char[],而genStringAsCharArray又可以轻松地写入Writer#write(char[])。这最终会“略微”提高效率,但是在谷歌搜索等大型和大量使用的应用程序中,这些小部件非常重要。

Tomcat的JSP编译器Jasper也是这样做的。检查static final char[] text1 = "some static text".toCharArray(); 设置。它确实如此

static final String text1 = "some static text";

而不是

String

最终会减少开销。它不需要围绕这些角色的整个{{1}}实例。

答案 7 :(得分:1)

如果在对代码进行概要分析后发现字符串的内存使用率存在问题,那么使用通用字符串压缩器并存储压缩字符串要好得多,而不是尝试使用UTF-8字符串进行轻微缩减在太空他们给你。使用英语字符串,通常可以将它们压缩为每个字符1-2位;大多数其他语言可能类似。每个字符达到< 1位是很难的,但如果你有大量数据,则可能。