public class 测试 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="a";
String t="b";
if(s==t) {
System.out.println("引用相同");
}else {
System.out.println("引用不相同");
}
}
//程序输出结果为
// 引用不相同
}
在上面程序中,我们用的是 String xxx=”nnn”这样的代码来创建String对象(并没有使用new运算符创建)。使用这样的方法创建的字符串对象是保存在常量池中的。内存结构如下图所示

=========================================================================
public class 测试 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="a";
String t="a";
if(s==t) {
System.out.println("引用相同");
}else {
System.out.println("引用不相同");
}
}
//程序输出结果为
// 引用相同
}
上面的程序中,我们还是使用的 String xxx=”nnn”这样的代码来创建String对象,(并没有使用new运算符创建)。使用这样的方法创建的字符串对象是保存在常量池中的。定义字符串常量时,编译器会先检查字符常量有没有重复。上面程序中,我们先定义了s,s的引用指向了a。然后,我们又定义了t,编译器发现t指向的值是a,和s指向的值是一样的。这时,编译器就不会再给字符a分配空间了,t和s将指向同一个a,内存结构如下图所示

所以上面的程序中,s是等于t的,输出结果为引用相同
这时,有过C语言指针基础的人可能就要问了,那岂不是我只要改了s或t两个中的任意一个对象,另外的一个对象也会被修改。比如我如果修改了s,那t的值也会跟着修改。这不会带来程序的歧义吗。我们可以写一个程序实验一下是不是这样的:
public class 测试 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s="a";
String t="a";
s="b";
System.out.println(s);
System.out.println(t);
if(s==t) {
System.out.println("引用相同");
}else {
System.out.println("引用不相同");
}
}
//程序输出的结果为
// b
// a
// 引用不相同
}
有C语言基础的人可能会以为内存模型是这样的

如果是这样的话,那程序输出的结果应该是b b 引用相同
可以我们发现程序结果并不是这样。
程序在执行到s=”b”;这行代码时,做了以下步骤:
(1)先处理“b”,创建了一个String对象,此时的内存模型为
(2)再把”b”的引用传给s,此时的内存模型为

所以,我们在修改s对象的时候,并不会影响到t对象。
==============================================================================
讲了那么多,搞的那么复杂,那我们在创建字符串对象的时候,能不能让编译器,不管遇到是相同的字符串,还是不相同的字符串,都给它分配内存(即使创建了两个相同的字符串对象,编译器也会给它们分配两个不同的内存,两个对象之间没有任何关系)
public class 测试 {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s=new String("a");
String t=new String("a");
if(s==t) {
System.out.println("引用相同");
}else {
System.out.println("引用不相同");
}
}
//程序输出结果为
// 引用不相同
}
内存结构如下图

上面的程序中,我们使用 String xxx=new String(”nnn”)这样的代码来创建String对象。使用new运算符创建对象,一定是给对象重新分配内存地址的。所以s和t的引用不一样。
有一说一,我觉得在开发中还是使用equals方法比较好,它比较的是对象的成员变量,而不是引用。
==============================================================================
这篇文章主要写的是我自己关于String类引用的理解。我没有了解过JVM和java底层编译原理。所以如果有错误的话,希望指出
本文深入探讨Java中String对象的创建方式,分析直接赋值与new关键字的区别,特别是对常量池的使用及引用相等性的理解。通过实例演示,解释了不同创建方式下,字符串对象在内存中的存储位置及其对程序运行的影响。
1220

被折叠的 条评论
为什么被折叠?



