String: 需要注意的问题
来源:互联网 发布:淘宝儿童服装冬季的 编辑:程序博客网 时间:2024/05/17 01:13
String中三种加法的区别
JAVA的确是一种令程序员陷入两难境地的言语, 确切的说是思想. 它提供了如此丰富的library,让程序员能够很容易的写出功能强大的程序. 同时它也封装了如此多的细节, 让程序员能够轻易的写出很拙略的程序. 它所代表的object指向思想设计之初是为了把程序员从纷繁复杂的编程细节中解放出来,来达到对已有程序的利用. 但是在编程 实际上又要求程序员了解其实现的细节而避免写出因调用已有library不正引起的performance慢的,耗费系统资源多的程序.通常成为一个优秀的JAVA程序员需要较长时间的经验积累,包括从程序的tuning中,或从其他有经验的程序员口中,才知道一定功能需要怎样实现,在程序中需要避免那些问题.但这往往是比较片面的,知其然而不知其所以然.我想大多数程序员都有类似的经历,举一个简单的例子,下面有三种对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 Class和StringBuffer Class的封装面纱看看它的内部实现.在JAVA中的String Class是一个不可变类,所有对一个Sting Object的改变都回导致一个新的String Object的生成.那么对tmp+=a中+符号的实现呢?如果你注意一下StringBuffer的Javadoc会发现.JDK对它的实现是
- tmp=(new StringBuffer().append(tmp).append("a")).toSting();
这样我们发现②这种方法在隐性生成了一个StringBuffer Object和一个String Object 再乘3就是六个object 的资源耗费.(还不包括String Class 和StringBuffer Class内部使用的Char[])而方法③只用了两个.也许有些程序员会对这些耗费不以为然,的确也是,不过在一些场景下它会成为perfamence的瓶颈.再回头看看①这种方法,它会被JAVA编译器编译为
- tmp=(new StringBuffer().append("a").append("b").append("c")).to String();
我们发现做的和③方法是同样的事.
对于方式①,Java编译器在编译期间就已经优化过。
java编译器对string常量表达式的处理和优化
首先把问题摆出来,先看这个代码
- String a = "ab";
- String b = "a" + "b";
- System.out.println((a == b));
1.true
"a" + "b" 的结果就是"ab",这样a,b都是"ab"了,内容一样所以"相等",结果true
一般java新人如是答。
2.false
"a" + "a"会生成新的对象"aa",但是这个对象和String a = "ab";不同,(a == b)是比较对象引用,因此不相等,结果false ,对java的String有一定了解的通常这样回答。
3.true
String a = "ab";创建了新的对象"ab"; 再执行String b = "a" + "b";结果b="ab",这里没有创建新的对象,而是从JVM字符串常量池中获取之前已经存在的"ab"对象。因此a,b具有对同一个string对象 的引用,两个引用相等,结果true.
能回答出这个答案的,基本已经是高手了,对java中的string机制比较了解。
很遗憾,这个答案,是不够准确的。或者说,根本没有运行时计算b = "a" + "b";这个操作.实际上运行时只有String b = "ab";
3的观点适合解释以下情况:
- String a = "ab";
- String b = "ab";
- System.out.println((a == b));
4.true
下面是我的回答:编译优化+ 3的处理方式 = 最后的true
- String b = "a" + "b";//编译器将这个"a" + "b"作为常量表达式,在编译时进行优化,直接取结果"ab",这样这个问题退化
- String a = "ab";
- String b = "ab";
- System.out.println((a == b));
这里有一个疑问就是String不是基本类型,像
- int secondsOfDay = 24 * 60 * 60;
下面简单证明我的推断,首先编译这个类:
- public class Test {
- private String a = "aa";
- }
- public class Test {
- private String a = "a" + "a";
- }
ok,真相大白了.根本不存在运行期的处理String b = "a" + "b";这样的代码的问题,编译时就直接优化掉了。
下面进一步探讨,什么样的string + 表达式会被编译器当成常量表达式?
String b = "a" + "b";
这个String + String被正式是ok的,那么string + 基本类型呢?
- String a = "a1";
- String b = "a" + 1;
- System.out.println((a == b)); //result = true
- String a = "atrue";
- String b = "a" + true;
- System.out.println((a == b)); //result = true
- String a = "a3.4";
- String b = "a" + 3.4;
- System.out.println((a == b)); //result = true
再注意看这里的string都是"**"这样的,我们换成变量来试试:
- String a = "ab";
- String bb = "b";
- String b = "a" + bb;
- System.out.println((a == b)); //result = false
再修改一下,把bb作为常量变量:
- String a = "ab";
- final String bb = "b";
- String b = "a" + bb;
- System.out.println((a == b)); //result = true
- String a = "ab";
- final String bb = getBB();
- String b = "a" + bb;
- System.out.println((a == b)); //result = false
- private static String getBB() {
- return "b";
- }
看来java(包括编译器和jvm)对string的优化,真的是到了极点了,string这个所谓的"对象",完全不可以看成一般的对象,java对string的处理近乎于基本类型,最大限度的优化了几乎能优化的地方。
转载来自:
http://blog.csdn.net/androidbluetooth/article/details/6626805
- String: 需要注意的问题
- 使用string.Format需要注意的一个性能问题
- 使用string.Format需要注意的一个性能问题
- String类型转Long类型需要注意的问题
- java中的String转int需要注意的问题
- 需要注意的问题
- 需要注意的问题
- string使用需要注意的地方。
- string使用需要注意的地方。
- string使用需要注意的地方。
- string使用需要注意的地方。
- string使用需要注意的地方。
- string使用需要注意的地方。
- string使用需要注意的地方。
- String.split需要注意的地方
- 需要注意的小问题
- 使用需要注意的问题
- toArray()需要注意的问题
- linux下编译ffmpeg ,以及x.264在linux下运行的配置
- 文章数据分析使用
- Javascript版时钟
- jquery Ztree树形控件
- GWT整合Struts2
- String: 需要注意的问题
- zoj 2420 Calendar
- Java中String背后的故事
- vmware7.1.1下安装ghostXP
- 个人成长与CMMI, 敏捷...
- 郁闷的几天
- XML样式表XSL初学教材,入门经典
- Flex页面跳转的五种实现方式
- iPhone - How set uinavigationbar height?