java基础——String和StringBuffe、StringBuilder

转自 http://blog.csdn.net/lonelyroamer/article/details/7354743

String的创建有两种形式,一种是直接放在双引号("");

                                            一种是直接用new的方式创建;

在Java中,String和StringBuffer,StringBuilder都能表示一个字符串。
String的定义是:表示一个字符串常量。那么,看下面的一段代码:
String str="abc";
str="def";
常量,基本数据类型的常量是不可变的,可是我们可以看到,这里所谓的字符串常量str是可变的。这是为什么呢?
引用数据类型的常量,指的是引用的对象不可变,而引用,也即句柄是可变的。也就是多,当一个String类型的字符串
改变时,实际上是它指向的内存单元发生了改变,原来的内存单元的内容并没有发生改变。
 
StringBuffer的定义是:表示一个字符串变量。StringBuffer strbuf="abc";这样的初始化是错误的,要想初始化一个
StringBuffer类型的字符串必须使用new来初始化,如
1、StringBuffer strbuf=new StringBuffer("abc");
2、strbuf=new StringBuffer("def");
3、strbuf.append("def");


由此可见,StringBuffer字符串变量,指的是不仅引用可变,引用的对象也是可变的。
下面的两个例子可以很好的说明这个问题。
1、
        String str1="abc";
        String str2=str1;
        StringBuffer str3=new StringBuffer("abc");
        StringBuffer str4=str3;
        str1=str1+str2;
        str3=str3.append(str4);
        System.out.println(str1);
        System.out.println(str2);
        System.out.println(str3);
        System.out.println(str4);
输出的结果:
abcabc
abc
abcabc
abcabc


2、
public class Test5
{
    public static void main(String[] args)
    {
        String str1="java";
        StringBuffer str2=new StringBuffer("java");
        test(str1);
        test(str2);
        System.out.println(str1);
        System.out.println(str2);
    }
    public static void test(String str)
    {
        str=str.replace("j", "i");
    }
    public static void test(StringBuffer str)
    {
        str.append("c");
    }
}

程序的输出结果为
java
javac

(String对象的处理确实与其他的对象有所区别,在深度克隆中也有体现,对它的处理更像是对一个基本数据类型的处理。
这主要就是因为它是一个常量的原因。)
 




字符串是一个引用数据类型
String对象肯定是存放在堆中的。关键在于,String对象是一个final的常量,JVM为了管理String和高效性
在堆中,会用一个
特殊的字符串池来保存字符串直接量
所谓的字符串直接量,就是指字符串由字符串、数值常量直接构成,没有变量,也没有方
例如
String a="abc";
String b="abc"+10;
String c="abc"+"def";
这样的字符串,JVM在编译的时候就能完全确定这个字符串,就可以在字符串池中创建该字符串,如果字符串池中已经有这样的
String,就让该变量直接指向在字符串池中的该字符串。
而另外一些不是字符串直接量的字符串
例如 
String a="abc"+"abc".lenght(); 
String b=a+"asc";
JVM无法在编译的时候就确定该字符串,就只能在程序运行期间,在堆中非字符串池中的地方开辟内存,存放这样的字符串。

1、String a="abc";
2、String b=new String("abcdef");
上面的两个创建字符串的方法到底分别创建了几个对象?
第1行,创建了一个对象,它是一个字符串直接量,直接被创建存放在字符串池中。
第2行,创建了2个对象,"abcdef"本身就是一个字符串直接量,被创建后存放在字符串池中,然后,它又作为一个参数,
传递给了构造器new String(),这样又在堆中非字符串池的地方开辟了块内存,创建了一个字符串对象。

那么,就在问去几个问题,下面的几段代码分别创建了几个对象
1、String a="ab";
2、String b="ab";
3、String d="abcd";
4、String c=a+"cd";
5、String e=new String("abcd")
6、String f="aaa"+"bbb";
答案:
第1行,1个、因为字符串池还是空的,不存在字符串"ab",所以在字符串池创建了一个对象"ab"。
第2行,0个、因为字符串池中"ab"已经存在,所以没有创建,直接将b指向"ab";
第3行,1个、因为也是在字符串池中创建了一个"abcd"对象
第4行,2个、先在字符串池中创建"cd",因为采用了变量,所以要在堆中非字符串池中在创建一个对象a+"cd";
第5行,1个、因为字符串池中已经存在"abcd",直接将他作为一个参数传给构造器new一个新的对象。
第6行,1个,因为在编译的时候就能确定f的值,所以只创建一个"aaabbb"到字符串池中;(很多人误解为3个)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值