String作为引用类型到底特殊在哪儿?

时间:2023-02-18 07:29:13
[code=Jav]
class Test {
public static void main(String[] args) {
String s = new String();
s = "lovechina!";
new Test().change(s);
System.out.println(s);

int[] x = new int[1];
x[0] = 5;
new Test().change(x);
System.out.println(x[0]);
}

void change(String s) {
s = "lovebeijing~~";
}

void change(int[] x) {
x[0] = 88;
}
}
[/code]
这段代码的结果是
lovechina!
88
----------------------------
疑问
作为引用类型的参数传递,传递的是对象的地址,方法可以将引用对象的值改变
int[]数组和String都为引用对象,为何一个改变了,一个没有改变呢?
都说String是特殊的引用类型,那它到底特殊在哪儿呢?
谢谢~!~

8 个解决方案

#1


String 的特殊在于它是个内容不可变的类型。

#2


代码块没有使用正确,没有缩进看起来很费劲
但是现在又不允许更改了……

#3


记住JAVA里面只有传值,没有传引用,没有传地址。

你可能有疑问:
void change(String s) {
s = "lovebeijing~~";

“这个参数s难道不是传的引用吗”

main中的:new Test().change(s); 
调用形式是,把s的地址的值传给函数void change(String s);
这两个s是不同的变量,相同的是他们的值,都是同一个地址。
s = "lovobeijing~~"只是在内存中字符串池里面开辟一个空间,放入这个字符串,然后把地址值传给s(函数里面的). 所以函数体里面不管怎么对s赋值,对外面的s没影响!
==================================
void change(int[] x) {
x[0] = 88;

传递给这个函数的x,也是传值,一个数组的首地址值。
而x[0] = 88;则是在x所代表的地址里面赋值为88,/

发现自己说不清楚了……反正大概就这样,记住是传值就好。全是传值!!!

#4


这样说吧,java里面只有几个基本数据类型:
primitive type :int short long byte float double char boolean.
还有就是引用类型。String s; 这个s并不是一个字符传,只是一个引用类型,他有值,他的值就是个地址,地址里面就是String的内容。

如果给一个函数传一个引用,那么他就是得到这个引用的地址值然后赋值给自己的参数(传值)。
如果是 s = "dddd";或者 s= new String("ddd");这两种方式都是对s重新赋值,就是重新给个地址值。

而x[0] = 88,这是在x所指的地址里面修改内容。 
所以就这样了。。

#5


理解这几点就好了。
1.Java中,String是不可变的对象。
所以,假设有如下代码。
[code=Jav]String s = "China";
s = "Beijing";[/code]
由于字符串不可变,"China"这个字符串对象并没有变成"Beijing"字符串。而仅仅是字符串引用s指向了一个新的字符串对象"Beijing",旧的字符串对象"China"仍然存在,并且没有任何改变。

2.Java只能传值。也就是说,如果你传了一个对象引用给某个方法。在这个方法内,实际上是使用的是这个对象引用的副本。你可以根据这个引用的副本改变被其指向的对象的状态。但是永远不可能用一个方法把一个对象引用指向另外一个对象(因为实际上是改变了对象引用的副本)。

结合以上这两点。你可以用一个方法改变一个数组的某个元素的值。但是不能通过一个方法将一个原本指向"lovechina"的字符串指针指向"lovebeijing"。

#6


String作为引用类型特殊的地方就是java中有一个字符串pool的概念。
String s = "ddddd";就是直接在pool中找是不是已经有“ddddd”,有的话直接返回地址,没有就在池中加入“ddddd”,然后再返回地址。


而String s = new String("dddd");则是在堆中开辟空间,同其他自定义类型的new一样。吧然后把返回的地址给s.最后还有看似无关紧要的一 步是在字符串池中开辟一个空间(如果池中原来没有“dddd”)放入“dddd”。

#7


你这代码里根本不涉及String的特殊性的内容,
弄懂JAVA对基本类型都是传值,对引用类型都是传引用的拷贝,就OK了

#8


看看 string 的源码
private final char value[];
有这么个属性
也就是每次生成一个string对象 这个对象所代表的字符数组就不能改变了
所以每次string的赋值和运算 都是重新生成了对象的 其中+ -运算实际上是对运算符进行了重载

#1


String 的特殊在于它是个内容不可变的类型。

#2


代码块没有使用正确,没有缩进看起来很费劲
但是现在又不允许更改了……

#3


记住JAVA里面只有传值,没有传引用,没有传地址。

你可能有疑问:
void change(String s) {
s = "lovebeijing~~";

“这个参数s难道不是传的引用吗”

main中的:new Test().change(s); 
调用形式是,把s的地址的值传给函数void change(String s);
这两个s是不同的变量,相同的是他们的值,都是同一个地址。
s = "lovobeijing~~"只是在内存中字符串池里面开辟一个空间,放入这个字符串,然后把地址值传给s(函数里面的). 所以函数体里面不管怎么对s赋值,对外面的s没影响!
==================================
void change(int[] x) {
x[0] = 88;

传递给这个函数的x,也是传值,一个数组的首地址值。
而x[0] = 88;则是在x所代表的地址里面赋值为88,/

发现自己说不清楚了……反正大概就这样,记住是传值就好。全是传值!!!

#4


这样说吧,java里面只有几个基本数据类型:
primitive type :int short long byte float double char boolean.
还有就是引用类型。String s; 这个s并不是一个字符传,只是一个引用类型,他有值,他的值就是个地址,地址里面就是String的内容。

如果给一个函数传一个引用,那么他就是得到这个引用的地址值然后赋值给自己的参数(传值)。
如果是 s = "dddd";或者 s= new String("ddd");这两种方式都是对s重新赋值,就是重新给个地址值。

而x[0] = 88,这是在x所指的地址里面修改内容。 
所以就这样了。。

#5


理解这几点就好了。
1.Java中,String是不可变的对象。
所以,假设有如下代码。
[code=Jav]String s = "China";
s = "Beijing";[/code]
由于字符串不可变,"China"这个字符串对象并没有变成"Beijing"字符串。而仅仅是字符串引用s指向了一个新的字符串对象"Beijing",旧的字符串对象"China"仍然存在,并且没有任何改变。

2.Java只能传值。也就是说,如果你传了一个对象引用给某个方法。在这个方法内,实际上是使用的是这个对象引用的副本。你可以根据这个引用的副本改变被其指向的对象的状态。但是永远不可能用一个方法把一个对象引用指向另外一个对象(因为实际上是改变了对象引用的副本)。

结合以上这两点。你可以用一个方法改变一个数组的某个元素的值。但是不能通过一个方法将一个原本指向"lovechina"的字符串指针指向"lovebeijing"。

#6


String作为引用类型特殊的地方就是java中有一个字符串pool的概念。
String s = "ddddd";就是直接在pool中找是不是已经有“ddddd”,有的话直接返回地址,没有就在池中加入“ddddd”,然后再返回地址。


而String s = new String("dddd");则是在堆中开辟空间,同其他自定义类型的new一样。吧然后把返回的地址给s.最后还有看似无关紧要的一 步是在字符串池中开辟一个空间(如果池中原来没有“dddd”)放入“dddd”。

#7


你这代码里根本不涉及String的特殊性的内容,
弄懂JAVA对基本类型都是传值,对引用类型都是传引用的拷贝,就OK了

#8


看看 string 的源码
private final char value[];
有这么个属性
也就是每次生成一个string对象 这个对象所代表的字符数组就不能改变了
所以每次string的赋值和运算 都是重新生成了对象的 其中+ -运算实际上是对运算符进行了重载