我在引擎中有一个方法我正在使用(andengine):
public final void setText(String pString){...}
我的应用是从静态int
每1秒更新一次得分mScoreText.setText(""+PlayerSystem.mScore);
问题在于这种方式每秒都会创建一个新的String对象,1分钟后我有66个String对象要通过GC和其他AbstractStringBuilders和init来收集......
我在andengine论坛上发现了一个部分解决方案:
private static StringBuilder mScoreValue = new StringBuilder("000000");
private static final char[] DIGITS = {'0','1','2','3','4','5','6','7','8','9'};
mScoreValue.setCharAt(0, DIGITS[(PlayerSystem.mScore% 1000000) / 100000]);
mScoreValue.setCharAt(1, DIGITS[(PlayerSystem.mScore% 100000) / 10000]);
mScoreValue.setCharAt(2, DIGITS[(PlayerSystem.mScore% 10000) / 1000]);
mScoreValue.setCharAt(3, DIGITS[(PlayerSystem.mScore% 1000) / 100]);
mScoreValue.setCharAt(4, DIGITS[(PlayerSystem.mScore% 100) / 10]);
mScoreValue.setCharAt(5, DIGITS[(PlayerSystem.mScore% 10)]);
mScoreText.setText(mScoreValue.toString());
但主要问题仍然存在,。toString()每次调用都会返回新对象
有什么方法可以解决这个问题吗?
答案 0 :(得分:3)
据我所知,没有办法解决Strings
不可变的事实,如果你的方法采用String,每次都必须创建一个新的。
答案 1 :(得分:3)
这听起来像是使用StringBuilder的好选择:
http://developer.android.com/reference/java/lang/StringBuilder.html
或StringBuffer:
http://developer.android.com/reference/java/lang/StringBuffer.html
推理是:
StringBuffer用于存储将被更改的字符串(不能更改String对象)。它会根据需要自动扩展。相关类:String,CharSequence。
StringBuilder是在Java 5中添加的。它在所有方面都与StringBuffer相同,只是它没有同步,这意味着如果多个线程同时访问它,可能会有麻烦。对于单线程程序,最常见的情况是,避免同步开销,使StringBuilder的速度稍快一些。
编辑: 你需要注意的一件事是你如何使用你选择的SB类。 原因是(在.Net中也是如此)如果你有这样的用法
StringBuilder sb = new StringBuilder(score.ToString() + "hello, world!");
你仍然有两个字符串连接操作,你可能实际上在那里制作3个字符串,一个用于score.ToString()
,一个用于将文字"hello, world!"
转换为字符串,另一个包含两个连在一起。
为了获得最佳结果,您需要使用SB的Append / insert / replace方法。
答案 2 :(得分:2)
首先,两分钟内120个物体是你不应该担心的,除非它们非常大。
其次,String类包含创建的所有字符串的池。所以,如果你这样做
String a = new String("Nabucodonosor King of Babilonia");
String b = new String("Nabucodonosor King of Babilonia");
然后Nabucodonosor King of Babilonia
只在内存中存储一次(但有两个String对象指向它)。检查字符串#intern()以获取详细信息。
最后,正如Daniel指出的那样,因为Strings是不可变的,所以没有使用Strings的解决方法。你可以做一些技巧(用旧值检查新值,只在它们不同的情况下创建String)但我怀疑它们会补偿增加的复杂性。