关闭

String对象的学习

标签: Stringjava
303人阅读 评论(0) 收藏 举报
分类:

下面是我学习java的String这一块的知识总结,如果有误,还请大神们予以指正,将不胜感激!

直接上码:

    String a1 = "moon" + "sun";   //第1行代码
	//"moon" + "sun"  其实就是 moonsun
	//Java在底层实现的时候其实是 StringBuilder sb = new StringBuilder("moon").append("sun");
	String b1 = "moonsun";  //在编译时就创建好了,存储在class文件中,所以在编译时就能确定b1的值
	System.out.println(a1 == b1);  //true

String对象中维护着一个string pool(常量池),上面第一行代码,编译器在编译时,将String a1 = "moon" + "sun"编译String a1 = "moonsun", "moon"和"sun"都是"常量",编译器将为这两个常量叠加得到固定的值,无须运行时再进行计算。s1的值是一个指向"moonsun"对象的引用地址。根据java的常量池机制,在编译的时候就可以确定b1所指向的字符串,直接指向常量池中的"moonsun"。所以a1和b1指向了同一字符串,最后会得到true的结果。常量池在编译期的时候就被确定的,并保存在编译好的class文件中的一些数据,在运行期被JVM装载,并可以动态扩充(String.intern),运行时常量池存在于栈中,而不是堆中

String str1 = new String("moon");
String str2 = new String("moon");

这行代码共产生了3个对象,一个是编译期保存在常量池中的"moon",另外两个是通过new在堆中生成的对象"moon",。

        String str = "jack chou";
	String str1 = "jack ";
	String str2 = "chou";
	String str3 = str1 + str2;    // 第四行代码
	System.out.println(str == str3);   //false
执行完前三行代码后,此时的常量池中有"jack " "chou"  "jack chou"这几个字符串, 编译器在编译第四行代码时,str1、str2只是两个普通变量,无法在编译时确定str3的值,于是就在运行的时候,系统会根据"str1 + str2"创建一个"jack chou"对象,所以最后才会表现出str== str3为false的结果。那第四行代码创建的"jack chou"这个字符串对象在哪?在堆还是在常量池?+的内部实现是用StringBuilder来实现的,String str3= str1+str2 内部是这样实现的:String str3 = newStringBuilder(str1).append(str2).toString();所以创建的字符串对象内存是在堆上分配的。

        String str = "jack chou";
	final String str1 = "jack ";
	final String str2 = "chou";
	String str3 = str1 + str2;    // 第四行代码
	System.out.println(str == str3);   //true

加上final将变量修饰成常量后,程序在被编译时,进行宏替换,直接将str1和str2替换成对应的变量值,所以在运行时输出的结果就是true了。

再来看一个关于字符串的列子:

public class Great  
{  
  
    public static void main(String[] args) {  
        String words = "hello";  
        change(words);  
        System.out.println(words);  //输出 hello  
    }  
  
    public static void change(String words)  
    {  
        words = words + "love";  
    }  
}

在调用方法change()时,在栈中开辟了change()内存空间,于是words形参指向了"hello"字符串,然后在change()方法体内改变了words,这步只是将形参words指向了另外一个字符串对象"hellolove"。栈区的change()函数执行完后,释放内存,main函数中的words并没有被改变。另外,String对象是不会改变的,如下面的代码:

        String str = "the day you went away";  //1
        String str = "I am back";   //2
        String str = "hey girl";
        /**
         * 执行第1行代码时,常量池中会有了一个字符串"the day you went away"
         * 到第2行代码时,str指向了"I am back"
         * 所以说我们在对str赋以字符串值时,str只是一个指向字符串的引用
         * str原先所指向的字符串是没有改变的
         * 如此一来,编译后的class文件中的常量池中就有了
         * "the day you went away"、"I am back"、"hey girl"这几个字符串
         */

对比一个数组的例子:

public class Arr
{
	public static void main(String[] args) {
		String[] str = new String[]{"you", "are", "so", "beautiful!"};
		for (String temp : str)
		{
			System.out.print(temp + " ");
		}
		System.out.println();
		
		edit_arr(str);
		for (String temp : str)
		{
			System.out.print(temp + " ");
		}
		System.out.println();
	}
	public static void edit_arr(String[] str1)
	{
		str[0] = "beauty";
	}
}</span>
结果是:


edit_arr()在栈区开辟内存时也是有一个形参str1指向了main函数中的实际变量str所指向的数组,这样的结果是,形参str1直接操作str所指向的内存对象,然后改变str指向对象的具体值。






0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:159378次
    • 积分:2193
    • 等级:
    • 排名:第17456名
    • 原创:86篇
    • 转载:13篇
    • 译文:1篇
    • 评论:20条
    文章分类
    最新评论
    xx