Java中字符串(String)的存储和赋值原理
2015-11-09 20:16
399 查看
可能很多java的初学者对String的存储和赋值有迷惑,以下是一个很简单的测试用例,你只需要花几分钟时间便可理解。
1.在看例子之前,确保你理解以下几个术语:
栈 :由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。
堆 :由JVM分配的,用于存储对象等数据的区域。
常量池 :在堆中分配出来的一块存储区域,用于存储显式的String,float或者integer.例如String str="abc"; abc这个字符串是显式声明,所以存储在常量池。
2.看这个例子,用JDK5+junit4.5写的例子,完全通过测试。
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import org.junit.Test;
/**
* @author Heis
*
*/
public class StringTest{
@Test
public void testTheSameReference1(){
String str1="abc";
String str2="abc";
String str3="ab"+"c";
String str4=new String(str2);
//str1和str2引用自常量池里的同一个string对象
assertSame(str1,str2);
//str3通过编译优化,与str1引用自同一个对象
assertSame(str1,str3);
//str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同
assertNotSame(str1,str4);
}
}
第一个断言很好理解,因为在解析的时候,"abc"被存储在常量池中,str1和str2的引用都是指向常量池中的"abc"。所以str1和str2引用是相同的。
第二个断言是由于编译器做了优化,编译器会先把字符串拼接,再在常量池中查找这个字符串是否存在,如果存在,则让变量直接引用该字符串。所以str1和str3引用也是相同的。
str4的对象不是显式赋值的,编译器会在堆中重新分配一个区域来存储它的对象数据。所以str1和str4的引用是不一样的。
1.在看例子之前,确保你理解以下几个术语:
栈 :由JVM分配区域,用于保存线程执行的动作和数据引用。栈是一个运行的单位,Java中一个线程就会相应有一个线程栈与之对应。
堆 :由JVM分配的,用于存储对象等数据的区域。
常量池 :在堆中分配出来的一块存储区域,用于存储显式的String,float或者integer.例如String str="abc"; abc这个字符串是显式声明,所以存储在常量池。
2.看这个例子,用JDK5+junit4.5写的例子,完全通过测试。
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import org.junit.Test;
/**
* @author Heis
*
*/
public class StringTest{
@Test
public void testTheSameReference1(){
String str1="abc";
String str2="abc";
String str3="ab"+"c";
String str4=new String(str2);
//str1和str2引用自常量池里的同一个string对象
assertSame(str1,str2);
//str3通过编译优化,与str1引用自同一个对象
assertSame(str1,str3);
//str4因为是在堆中重新分配的另一个对象,所以它的引用与str1不同
assertNotSame(str1,str4);
}
}
第一个断言很好理解,因为在解析的时候,"abc"被存储在常量池中,str1和str2的引用都是指向常量池中的"abc"。所以str1和str2引用是相同的。
第二个断言是由于编译器做了优化,编译器会先把字符串拼接,再在常量池中查找这个字符串是否存在,如果存在,则让变量直接引用该字符串。所以str1和str3引用也是相同的。
str4的对象不是显式赋值的,编译器会在堆中重新分配一个区域来存储它的对象数据。所以str1和str4的引用是不一样的。
相关文章推荐
- JAVA环境配置
- 实践hibernate的应用——struts2+hibernate的简单学生信息管理
- 不可变的集合带来的意外
- Java生成MD5算法
- SpringMVC访问静态资源的三种方式
- 设计模式01-单例设计模式
- Java基础学习23(abstract)
- 从头认识java-7.5 怎样通过继承扩展接口?
- 自己实现LinkedListJAVA103-104
- Caused by: java.net.SocketException: Connection reset
- JavaWeb学习篇——使用通用工厂类解耦MVC框架
- Spring进阶一:Spring开发环境搭建
- Java中日期类型和mysql中日期类型进行整合
- spring 国际化
- 用cxf生成webservice的java客户端代码
- java基础第5天(构造代码块、this关键字、构造函数)
- Java transient关键字使用小记
- Java的HashMap底层实现详解
- JAVA反射机制的学习
- 【Java基础】Integer包装类的缓冲池问题