String对象创建内存分析浅解

package com.lib.String;
//总结
//1、栈中用来存放一些原始数据类型的局部变量数据和对象的引用(String,数组.对象等等)但不存放对象内容
//2、堆中存放使用new关键字创建的对象.
//3、字符串是一个特殊包装类,其引用是存放在栈里的,而对象内容必须根据创建方式不同定(常量池和堆).有的是编译期就已经创建好,存放在字符串常 量池中,而有的是运行时才被创建.使用new关键字,存放在堆中。
//4、final 修饰的StringBuffer 变量是否可以追加。
public class StringTest { 
	/**
	 * ab的哈希值   是a的哈希值 左移 5位+1
	 */
	public static void test1(){
		String name = "abc";
		String name1 = "b";
		System.out.println(name.hashCode()+"---"+name1.hashCode());
		int h = 0;
		for(int i=0; i<2; i++){
			h = 31*h +(97+i);
		}
		System.out.println(h);
		System.out.println((97<<5)+1);
	} 
	/**
	 *  测试字符串的创建
	 */
	//答案1:如果常量池中没有 "ab" 值,1个   没有 2个
	//	JAVA虚拟机首先在字符串池中查找是否已经存在了值为"ab"的这么一个对象,它的判断依据是String类equals(Object obj)方法的返回值。
	//	如果有,则不再创建新的对象,直接返回已存在对象的引用;
	//	如果没有,则先创建这个对象,然后把它加入到字符串池中,再将它的引用返回
	
	//答案3:
	//	当执行String a="abc";时,JAVA虚拟机会在栈中创建三个char型的值'a'、'b'和'c',然后在堆中创建一个String对象,
	//	它的值(value)是刚才在栈中创建的三个char型值组成的数组{'a','b','c'},最后这个新创建的String对象会被添加到字符串池中(重要)。
	//	如果我们接着执行String b=new String("abc");代码,由于"abc"已经被创建并保存于字符串池中,
	//	因此JAVA虚拟机只会在堆中新创建一个String对象,但是它的值(value)是共享前一行代码执行时在栈中创建的三个char型值值'a'、'b'和'c'。
	public static void test2(){
		//问题3:执行过程
		String a = "ab";
		String b = "ab";
		String c = "a"+"b"; //1.编译之后就是    String c = "ab"; 
							//2.使用引号包含文本的方式创建的String对象之间使用“+”连接产生的新对象才会被加入字符串池中
		//问题1:下面这行代码运行过程中创建了几个对象
		String d = new String("ab");
		String f = a+b;
		String g = a+"b";  //所产生的新对象"aab"不会被加入字符串池中
		System.out.println("a ==b "+(a==b));		//true
		System.out.println("a ==c "+(a==c));		//true
		System.out.println("a ==d "+(a==d));		//false
		System.out.println("abab ==f "+(f=="abab"));//false
		System.out.println("aab ==g "+(g=="aab"));  //false
	}
	/**
	 * 模拟 equlas 方法
	 * 1、先用 == 判断   地址是否相同
	 * 2、先判断是否是Sting对象
	 * 3、
	 */
	public static void test3(){
		String a = "ab";
		boolean b = a.equals("ab");
	}
	/**
	 *  final  修饰的类变量
	 * 重要: 可见,final只对引用的"值"(即内存地址)有效,它迫使引用只能指向初始指向的那个对象,改变它的指向会导致编译期错误。
	 *      至于它所指向的对象 的变化,final是不负责的。
	 */
	//答案2:可以追加,原因在(重要:)中阐述
	public static void test4(){
		final StringBuffer a = new StringBuffer("aaa");
		//问题2:final 修饰的变量a 是否可以追加?
		a.append("bbb");
		System.out.println(a.toString());
	} 
	/**
	 * 测试常量池中是否存在该字符串   intern()方法的使用
	 */
	public static void test5(){
		 // 使用char数组来初始化a,避免在a被创建之前字符串池中已经存在了值为"abcd"的对象
        String a = new String(new char[] { 'a', 'b', 'c', 'd' });  
        //String a = "abcd";
		//String a = new String("abcd");
        //解释来自jdk : 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串(相当于 String b = a;)。
        //否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
        String b = a.intern();
        String c = "abcd";
        System.out.println(b==c);
        if (b == a) {
              System.out.println("b被加入了字符串池中,没有新建对象");
        } else {
              System.out.println("b没被加入字符串池中,新建了对象");
        }
	}

	//部分来自:  http://blog.csdn.net/phantomes/article/details/9789757
	public static void main(String[] args) {
		//test1();
		test2();
//		test3();
//		test4();
		test5();
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值