java中String和new String还有对象中的String字符串在内存中的存储

 参考自http://blog.csdn.net/zhangjg_blog/article/details/18319521 的博客,很多知识和代码都来源此,感兴趣的同学可以去看看

    一直以来,所有人都说,java中的String类型是不可变的,可是为什么不可变确很少有人说的透彻,String和new String的区别,对象中的String和直接定义一个String是否有区别,一直都是一知半解。看了很多文档都是各种猜测,没有具体代码来证明。今天看了上面的博客做了一些测试,有一些心得。String类型一直是一个特殊的数据类型,在创建的时候就是不可变的,会在Stringconstant pool中创建一个常量,当我们再次创建一个字符串的时候,jvm会先去String constant pool 中检索这个这个常量是否存在,如果存在则将引用返回,如果不存在,则创建新的常量,然后将引用返回。那么使用new String的方法创建?或者是在一个对象的实例中创建一个字符串?内存中这个值会如何存储?是在Heap中直接开辟空间存储,还是会在Stringconstant pool 中创建,然后在Heap中创建一个引用?接下来,通过代码来证明,在内存中String究竟是如何存储的

   首先是Stringnew String的区别

	public static void main(String[] args) throws Exception {
		String hello="hello world";
		String xx=new String("hello world");
		String yy="hello world";
		
		//输出判断内存地址是否相等
		System.out.println("xx==hello : "+ (xx==hello));
		System.out.println("yy==hello : "+ (yy==hello)+"\n");
		
		//通过反射修改hello的value值
		Field hello_field=String.class.getDeclaredField("value");
		hello_field.setAccessible(true);
		char[] value=(char[])hello_field.get(hello);
		value[5]='_';
		
		//首先输出修改结果
		System.out.println("Hello: "+hello+"\n");
		
		//然后判断内存地址是否有变化
		System.out.println("xx==hello : "+ (xx==hello));
		System.out.println("yy==hello:"+(hello==yy));
		System.out.println("xx==yy:"+(xx==yy)+"\n"); 
		
		//最后输出所有值的结果
		System.out.println("xx: "+xx);
		System.out.println("yy: "+yy);
		System.out.println("Hello: "+hello);
	}
 代码执行结果
xx==hello : false
yy==hello : true

Hello: hello_world

xx==hello : false
yy==hello:true
xx==yy:false

xx: hello_world
yy: hello_world
Hello: hello_world

 根据结果可以判断,无论是String还是new String最终都指向了String constant pool中,只不过是String直接指向了Stringconstant pool中。而new String是在Heap中创建了一个指向String constant pool中的引用。那么,对象中String是否也是这样的?那么我们是否可以这样推测,在java中所有的String类型的字符串,最终都会指向Stringconstant pool  中?

  然后是StringObject的区别

import java.lang.reflect.Field;

public class StringTest {

	public String name="hello world"; 
	
	public String phone; 
	
	public StringTest(String phone) {
		// TODO Auto-generated constructor stub
		this.phone=phone;
	}
	
	public static void main(String[] args) throws Exception {
		StringTest a = new StringTest("hello world");
		StringTest b = new StringTest("hello world");
		String c = "hello world";
		String e = new String("hello world");
		
		//首先判断不同对象中的字符串地址是否相等
		System.out.println("a.name==a.phone:"+(a.name==a.phone));
		System.out.println("a.name==b.phone:"+(a.name==b.phone));
		System.out.println("a.name==c:"+(a.name==c));
		System.out.println("e==c:"+(e==c)+"\n");
		
		//然后修改c在内存中的值
		Field hello_field=String.class.getDeclaredField("value");
		hello_field.setAccessible(true);
		char[] value=(char[])hello_field.get(c);
		value[5]='_';
		
		//首先判断不同对象中的字符串地址是否相等
		System.out.println("a.name==a.phone:"+(a.name==a.phone));
		System.out.println("a.name==b.phone:"+(a.name==b.phone));
		System.out.println("a.name==c:"+(a.name==c));
		System.out.println("e==c:"+(e==c)+"\n");
		
		//直接输出值判断是否发生变化
		System.out.println("a.name: "+a.name);
		System.out.println("b.name: "+b.name);
		System.out.println("a.phone: "+a.phone);
		System.out.println("b.phone: "+b.phone);
		System.out.println("c: "+c);
		System.out.println("e: "+e);
	}
	
}
 代码执行结果
a.name==a.phone:true
a.name==b.phone:true
a.name==c:true
e==c:false

a.name==a.phone:true
a.name==b.phone:true
a.name==c:true
e==c:false

a.name: hello_world
b.name: hello_world
a.phone: hello_world
b.phone: hello_world
c: hello_world
e: hello_world

  根据执行结果可以看出,不同对象中的String值相等时,其指向的是同一个String constant pool中的地址,如果我们修改了其中一个值得时候,所有的引用都会发生改变,而且其内存地址的比较并没有发生变化。所以我们的推测应该是正确的,因时间关系,没有了测试数组和其他的关于String类型的字符串是否也是如此,不过根据上面的结果,我们应该可以大胆猜测,java中,如果定义了String类型的字符串,最终的都存在String constant pool 中。如果有什么意见或建议请在下方留言,再次感谢原博主










评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值