java所代表的object指向思想设计之初是为了把程序员从纷繁复杂的编程细节中解放出来,来达到对已有程序的利用。但是在编程实际上又要求程序员了解其实现的细节,而避免写出因调用已有library不正引起的performance慢的、耗费系统资源多的程序。通常成为一个优秀的Java程序员需要较长时间的经验积累,包括从程序的tuning中或从其他有经验的程序员口中,才知道一定功能需要怎样实现,在程序中需要避免那些问题。但这往往是比较片面的,知其然而不知其所以然。
我想大多数程序员都有类似的经历,举例子,下面有三种对String的累加操作。
tmp += "a";
tmp += "b";
tmp += "c";
③String tmp = null;
StringBuffer buf = new StringBuffer();
buf.append("a");
buf.append("b");
buf.append("c");
tmp = buf.toString();
有些Java程序员无视它们的区别。有些程序员知道第三种方法好,一直在用而不知其为什么好,以至于作为经验教条的传授给Java新手。真正的答案是什么呢?让我们揭开Java的String类和StringBuffer类的封装面纱,看看它的内部实现。
在Java中的String是一个不可变类,所有对一个String Object的改变都会导致一个新的String Object的生成。
那么对"tmp += a"中"+"符号的实现呢? 如果你注意一下StringBuffer的Javadoc会发现,JDK对它的实现是:
tmp = (new StringBuffer().append(tmp).append("a")).toSting();
这样我们发现②这种方法在隐性生成了一个StringBuffer Object和一个String Object,再乘3就是6个object 的资源耗费。(还不包括String类和StringBuffer类内部使用的char[])。而方法③只用了两个。
也许有些程序员会对这些耗费不以为然,但在一些场景下它会成为perfamence的瓶颈。
再回头看看①这种方法,它会被Java编译器编译为:
tmp = new StringBuffer().append("a").append("b").append("c").toString();
我们发现①做的和③方法是同样的事。
我想大多数程序员都有类似的经历,举例子,下面有三种对String的累加操作。
①String tmp = "a" + "b" + "c";
②String tmp = null;tmp += "a";
tmp += "b";
tmp += "c";
③String tmp = null;
StringBuffer buf = new StringBuffer();
buf.append("a");
buf.append("b");
buf.append("c");
tmp = buf.toString();
有些Java程序员无视它们的区别。有些程序员知道第三种方法好,一直在用而不知其为什么好,以至于作为经验教条的传授给Java新手。真正的答案是什么呢?让我们揭开Java的String类和StringBuffer类的封装面纱,看看它的内部实现。
在Java中的String是一个不可变类,所有对一个String Object的改变都会导致一个新的String Object的生成。
那么对"tmp += a"中"+"符号的实现呢? 如果你注意一下StringBuffer的Javadoc会发现,JDK对它的实现是:
tmp = (new StringBuffer().append(tmp).append("a")).toSting();
这样我们发现②这种方法在隐性生成了一个StringBuffer Object和一个String Object,再乘3就是6个object 的资源耗费。(还不包括String类和StringBuffer类内部使用的char[])。而方法③只用了两个。
也许有些程序员会对这些耗费不以为然,但在一些场景下它会成为perfamence的瓶颈。
再回头看看①这种方法,它会被Java编译器编译为:
tmp = new StringBuffer().append("a").append("b").append("c").toString();
我们发现①做的和③方法是同样的事。