题目

public class Exam10{ 
String str=new String("good"); 
  	char[]ch={'a','b','c'}; 
  	public static void main(String args[]){ 
  	Exam10 ex=new Exam10(); 
  	ex.change(ex.str,ex.ch); 
  	System.out.print(ex.str+" and "); 
  	System.out.print(ex.ch); 
} 
public void change(String str,char ch[]){ 
  str="test ok"; 
  ch[0]='g';  
  } 
}

答案

good
gbc

简述:String和char[]两个对象传入change方法修改其中的值,但是String修改后,原变量值不变,但是char[]数组中字符被成功修改。
先来提前说一下原因:
从题目代码可以看见,两个对象被传入一个方法中,改变了其中的内容,但是原变量中,String并没有被修改,char[]被修改了。想搞明白这道题,先要明白String str = “ggzx”;str是一个引用变量, “ggzx”才是真正的对象,该对象保存在内存块中,str引用变量只是指向了该内存块。
String是一个类,该类中使用private final char[] value;保存值,因为该属性被final修饰,该数组无法指向其他的地址,我们平时所谓的修改string的值,底层代码其实都是开辟新内存块保存新的值,让引用变量指向这块内存。
String name = “ggzx”;
name = “ggzxy”;
对于这两行代码,两个字符串都占据不同的内存块,name变量是一个引用,该引用指向一个内存块,在初始化时指向”ggzx”内存块,当修改后创建新的内存块,并指向”ggzxy”内存块。change方法中的str和原变量是两个引用变量,change方法中修改str的值,只是创建新内存块并更改了方法中的str的指向,原引用变量及其内存块都未更改,所以原变量值不发生变化。
而char[]数组不像String,char[]只是普通的对象,也没有被 final修饰,ch引用变量传入change方法,传入后指向的仍是同一块内存,我们更改了两者指向的同一块内存,那么在原变量中肯定能看到修改的痕迹。


先来分析一下传参的过程,对于原变量str和方法参数中的str,他们都是指向的同一块内存空间

java string修改某个位置的值 修改string中的值_方法参数

下面我们来证明一下,如果我们让方法参数中str指向null并返回,,那么如果上图是正确的,那么原变量肯定不是null,返回String是null

java string修改某个位置的值 修改string中的值_引用变量_02

下面我们再来分析,为什么String修改后,原变量值不变,但是char[]中值变化了。

对于一般对象,若在方法中修改了其中的内存,那么其实也是修改了原变量指向内存块的值,所以会变。原char[]数组变化是正常现象

java string修改某个位置的值 修改string中的值_引用变量_03

但是String比较特别,String 内部使用的final修饰的char[]数组,我们在学习final的过程中了解到,final修饰的对象是无法指向其他对象的,即String类的char[]数组无法指向其他的内存块但是为什么我们可以使用str = “”;来修改str的内容呢,str只是个引用,真正的对象是后面的内容 ,例如str=“”,真正的对象是"",他被保存在一个内存块中,str指向内存块。

对于被final修饰的

当我们定义了一个str字符对象时,str指向该String所在内存块,该内存块中有一保存char[]数组的内存块(被final修饰),里面保存着该数组的地址,因为被final 修饰,该内存块无法指向其他地址。

java string修改某个位置的值 修改string中的值_方法参数_04

但是如果我们想要修改str引用变量指向对象的值,我们创建一个新的String对象的内存块,里面保存了新的值,让str指向新内存块即可,事实上,String是无法修改的,但是我们平时修改,其实就是创建了新的变量,然后原有的引用变量指向了新的内存块。

java string修改某个位置的值 修改string中的值_java_05