例如,您想要反转一个字符串,有两种方法:
第一
String a = "StackOverFlow";
a = new StringBuffer(a).reverse().toString();
,第二是:
String a = "StackOverFlow";
StringBuffer b = new StringBuffer(a);
a = b.reverse().toString();
在上面的代码中,我有两个问题:
1)在第一个代码中,java在StringBuffer
之前在内存中创建了一个“虚拟对象”reverse
并更改为String
。
2)在上面的代码中,首先会比第二代更优化,因为它使GC更有效地工作? (这是我想问的一个主要问题)
答案 0 :(得分:5)
两个片段都会创建相同数量的对象。唯一的区别是局部变量的数量。这可能甚至不会改变堆栈上的值等等 - 只是在第二个版本的情况下,其中一个堆栈槽(b
)有一个名称。
区分对象和变量非常重要。编写最易读的代码也很重要,而不是尝试微优化。一旦你有了明确的工作代码,你应该测量它是否足够快以满足你的要求。如果不是,您应该对其进行分析,以确定最有效地进行更改的位置,并优化该部分,然后重新测量等。
答案 1 :(得分:1)
StringBuffer b
不是虚拟对象,是引用;基本上只是一个指针,它位于堆栈中并且内存非常小。因此,不仅性能没有差别(GC与此示例无关),但Java编译器可能会完全删除它(除非它在代码中的其他位置使用)。
答案 2 :(得分:1)
StringBuffer
创建一个非常真实的,而不是“虚拟对象”。b
的其他引用,否则优化程序有足够的信息可以在环境完成b
后立即对其进行垃圾收集toString
b
没有变量的事实不会使new
创建的对象不那么真实。编译器可能也会将两个片段优化为相同的字节码。
答案 3 :(得分:0)
回答第一个问题,是的,Java将创建一个StringBuffer对象。它的工作方式与你的想法非常相似。
对于第二个问题,我很确定Java编译器会为您处理这个问题。编译器并非没有错误,但我认为在这样一个简单的例子中它将优化字节代码。
只是提示,Java Strings是不可变的。这意味着他们无法改变。因此,当您为String分配新值时,Java将分割出一块内存,将新的String值放入其中,并将该变量重定向到新的内存空间。之后,垃圾收集器应该来并清除旧字符串。