我有这个测试循环:
String str_1;
Object an_object_var = new Object();
long startTime = System.nanoTime();
for(int i = 0; i < 100000; i++)
{
an_object_var=(Object)i;
str_1 = an_object_var.toString();
}
long endTime = System.nanoTime();
long timig = endTime - startTime;
System.out.println(timig);
StringBuilder sb = new StringBuilder();
an_object_var = new Object();
System.out.println(new Date());
startTime = System.nanoTime();
for(int i = 0; i < 100000; i++)
{
an_object_var=(Object)i;
sb.delete(0, sb.length());
sb.insert(0, an_object_var);
}
endTime = System.nanoTime();
timig = endTime - startTime;
System.out.println(timig);
我没有连接字符串,只是做了一些拆箱。第一个循环比第二个循环快得多(15441625 vs 26869129纳秒。我在NetBeans上运行它们)。但是,只要字符串是不可变的,我就会在第一个循环中在内存中创建100000个变量(直到下一个Garbage Colector传递)。 在第一个循环中是否存在内存惩罚,而在第二个循环中没有发生?
答案 0 :(得分:2)
是的,区别在于编译器可以从第一个示例中删除更多代码,因为它没有做任何有用的事情。第二个循环更难以优化为零。
你遇到的另一个问题是第一个循环触发了整个方法的优化,在这种情况下,JIT没有关于第二个循环的信息,所以它也不能对它进行优化。我建议你把两个测试放在他们自己的方法中然后运行多次。确保测试每个运行至少2秒。
BTW如果您使用
sb.setLength(0);
sb.append(i);
而不是
an_object_var=(Object)i;
sb.delete(0, sb.length());
sb.insert(0, an_object_var);
这样可以避免造成任何垃圾。
答案 1 :(得分:1)
因为垃圾收集器不允许内存泄漏,所以没有内存惩罚,因为这句话:
str_1 = an_object_var.toString();
将导致GC在更改引用之前释放旧的字符串对象 编辑:有人说你不能声称gc会这样做,即使如此,你可以这样确定自己:
for(long i = 0; i < 1000000000000; i++)
{
an_object_var=(Object)i;
str_1 = an_object_var.toString();
}
我怀疑记忆能否存活下来!