论 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究竟是如何存储的

首先是String和new 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 中?
然后是String和Object的区别
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 中。如果有什么意见或建议请在下方留言,再次感谢原博主


本文来自 中二程序员 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/penyoudi1/article/details/79163567?utm_source=copy

本文来自 中二程序员 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/penyoudi1/article/details/79163567?utm_source=copy

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值