Java:使用新Object时两种方式不同

时间:2012-03-09 15:13:14

标签: java object

例如,您想要反转一个字符串,有两种方法:

第一

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更有效地工作? (这是我想问的一个主要问题)

4 个答案:

答案 0 :(得分:5)

两个片段都会创建相同数量的对象。唯一的区别是局部变量的数量。这可能甚至不会改变堆栈上的值等等 - 只是在第二个版本的情况下,其中一个堆栈槽(b)有一个名称。

区分对象变量非常重要。编写最易读的代码也很重要,而不是尝试微优化。一旦你有了明确的工作代码,你应该测量它是否足够快以满足你的要求。如果不是,您应该对其进行分析,以确定最有效地进行更改的位置,并优化该部分,然后重新测量等。

答案 1 :(得分:1)

StringBuffer b不是虚拟对象,是引用;基本上只是一个指针,它位于堆栈中并且内存非常小。因此,不仅性能没有差别(GC与此示例无关),但Java编译器可能会完全删除它(除非它在代码中的其他位置使用)。

答案 2 :(得分:1)

  1. 第一种方法是为StringBuffer创建一个非常真实的,而不是“虚拟对象”。
  2. 除非在代码的最后一行下面有b的其他引用,否则优化程序有足够的信息可以在环境完成b后立即对其进行垃圾收集toString
  3. b没有变量的事实不会使new创建的对象不那么真实。编译器可能也会将两个片段优化为相同的字节码。

答案 3 :(得分:0)

回答第一个问题,是的,Java将创建一个StringBuffer对象。它的工作方式与你的想法非常相似。

对于第二个问题,我很确定Java编译器会为您处理这个问题。编译器并非没有错误,但我认为在这样一个简单的例子中它将优化字节代码。

只是提示,Java Strings是不可变的。这意味着他们无法改变。因此,当您为String分配新值时,Java将分割出一块内存,将新的String值放入其中,并将该变量重定向到新的内存空间。之后,垃圾收集器应该来并清除旧字符串。