`
willsunforjava
  • 浏览: 166354 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java 字符串解惑

 
阅读更多

 

1. String创建

Java String的不可变的(immutable),查看源码可以知道,String使用private final char[] value来实现字符串存储的。

String的创建方式有两种,如下:

(1) String str = "aaa";

(2) String str = new String("aaa");

 

这两种的区别是:

(1)是在编译期,由于两个常量相加,编译器会进行优化,在编译的时候就处理成“ab”了;

(2)是在运行期,这里的"aaa"本身就是contant pool中的一个对象,而在运行时执行new String()时,将pool中的对象复制一份放到heap中,并且把heap中的这个对象的引用交给str持有。这条语句就创建了两个对象。这是个Java面试经常出现的问题,但是莫枢大牛(http://rednaxelafx.iteye.com)写了一篇《请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧》,深入学习了一下,其实没那么简单

 

还有一种是java可以直接使用+对两个字符串进行连接:

String str1 = "a";

String str2 = "b"

String str3 = str1+str2;

因为Java对String类型重载了加号(+)操作符,这种在代码编译的时候,会处理成StringBuilder(JDK 5及以上)

或StringBuffer(JDK 5 以下)进行连接。如会变成

String str3 = (new StringBuilder("a")).append(str2).toString();

详细的源码可以查看%JAVA_HOME%/lib/tools.jar中,com.sun.tools.javac这个包下面的代码。

 

扩展1:常量池(Constant Pool)

在java编译好的class文件中,有个区域称为Constant Pool,它是一个由数组组成的表,用来存储程序中使用的各种常量,包括Class、String、Integer等各种基本的Java数据类型

对于值相同的String常量,在Constant Pool中只会创建一个,所以在编译好的class文件中,我们只能找到一个string常量。

在程序执行时,Constant Pool会存储在Method Area中,而不是堆中。详细的java内存区域划分见博文Java内存区域学习笔记

 

2. String intern方法

官方API的解释,返回字符串对象的规范化表示形式。即返回一个字符串,内容与此字符串相同,但它保证来自字符串池中。

尽管在输出中调用intern方法并没有什么效果,但是实际上后台这个方法会做一系列的动作和操作。在调用"ab".intern()方法的时候会返回"ab",但是这个方法会首先检查字符串池中是否

有"ab"这个字符串,如果存在则返回这个字符串的引用,否则就将这个字符串添加到字符串池中,然后返回这个字符串的引用。

 

3. StringBuffer的创建

本身String是不可变的,但是却可以如

String a = "a";

a = a+"b";

StringBuffer扮演了String的可变配套类角色。

 

StringBuffer sb = new StringBuffer("abc")

sb = sb.append("22");

这两个代码产生了两个对象,“abc”本身与经过new创建出来sb,StringBuffer的特点是改变对象本身而不是创建新的对象,因此,此处的sb.append(“22”)都是对同一个对象进行处理。

这个也是StringBuffer比new String()性能好的原因,因为StringBuffer对字符串的改变不会生成新的对象。

 

 

4. StringBuffer与StringBuilder的异同

其异同为:一、长度都是可扩充的;二、StringBuffer是线程安全的,StringBuilder是线程不安全的。

 

StringBuilder一个可变的字符序列是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。

该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。

如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。如果去掉线程安全,那两者就基本一样的。查看源码可以知道

StringBuffer所有方法(构造方法除外,因为没有必要)签名中都使用 synchronized 限定。


分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics