题目
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,他们都是指向的同一块内存空间 下面我们来证明一下,如果我们让方法参数中str指向null并返回,,那么如果上图是正确的,那么原变量肯定不是null,返回String是null 下面我们再来分析,为什么String修改后,原变量值不变,但是char[]中值变化了。 对于一般对象,若在方法中修改了其中的内存,那么其实也是修改了原变量指向内存块的值,所以会变。原char[]数组变化是正常现象 但是String比较特别,String 内部使用的final修饰的char[]数组,我们在学习final的过程中了解到,final修饰的对象是无法指向其他对象的,即String类的char[]数组无法指向其他的内存块
但是为什么我们可以使用str = “”;来修改str的内容呢,str只是个引用,真正的对象是后面的内容 ,例如str=“”,真正的对象是"",他被保存在一个内存块中,str指向内存块。 对于被final修饰的 当我们定义了一个str字符对象时,str指向该String所在内存块,该内存块中有一保存char[]数组的内存块(被final修饰),里面保存着该数组的地址,因为被final 修饰,该内存块无法指向其他地址。 但是如果我们想要修改str引用变量指向对象的值,我们创建一个新的String对象的内存块,里面保存了新的值,让str指向新内存块即可,事实上,String是无法修改的,但是我们平时修改,其实就是创建了新的变量,然后原有的引用变量指向了新的内存块。
|