java中String的传参和不可变问题探究

         今天写程序时用到了String.replace(char oldChar, char newChar)方法。感觉很困惑,本来这个方法时新的字符代替旧的字符,可我发现使用了以后没有替换。这是为什么呢?经过思考如下:

先贴上代码:

public class Test {
	public static void main(String[] args){
		
		Test test = new Test();
		String s = new String("hello");
		test.notice(s);
		System.out.println(s);
		
	}
	public static void notice(String str){
		str = str.replace('h', 'x');
	}
}



输出结果为:hello

我们会发现,字符串hello的‘h’没有被替换成‘x’。

原因如下:

1:String的参数传递传递的是值而不是引用,为什么一定要传值呢?

2:打开String类的源代码我们可以看到String类时用final修饰的,是不能被改变的。

3:而且String类的底层是由一个字符数组去实现的,数组的值实在初始化的时候就决定的,然而如果说java的String类型可以改变,那么用户可以随便       的访问数组,造成了安全隐患。


我们来分析为什么2中说String类型不可以被改变:

先来看这一段代码:

public class Test {
	public static void main(String[] args){
		
		String s = "x";
		s = "k";
		
		}
}

在String s = “x”这行加上断点调试的结果:


这回再看下一行的调试结果:


我们会发现,s都是同一个String对象,但是他们的id不相同。

这就是String的不可变性:深究原因我们会发现:java中的String只能重新创建,而不能改变。

就上面的例子来说,s开始时为x,这时s是一个对象,当s的结果被我们修改成k之后,并不是k覆盖了s,而是在内存中虚拟机又为我们创建可k这个对象,然后将s指向了k,然而。x这个字符串还是存在的,只是我们的对象s没有了指向他的指针罢了。

画一张内存图大家也许会更清楚:



再看看我们的replace这个函数,当我们用值传递时,字符串也会被改变,但是原来的字符串依然在内存中,只是原来的对象指向了新创建的字符串:可以看到replace函数的源码中有:

pu<span style="font-size:12px;">blic String replace(char oldChar, char newChar) {
	if (oldChar != newChar) {
	    int len = count;
	    int i = -1;
	    char[] val = value; /* avoid getfield opcode */
	    int off = offset;   /* avoid getfield opcode */

	    while (++i < len) {
		if (val[off + i] == oldChar) {
		    break;
		}
	    }
	    if (i < len) {
		char buf[] = new char[len];
		for (int j = 0 ; j < i ; j++) {
		    buf[j] = val[off+j];
		}
		while (i < len) {
		    char c = val[off + i];
		    buf[i] = (c == oldChar) ? newChar : c;
		    i++;
		}
		return new String(0, len, buf);
	    }
	}
	return this;
    }</span>

我们可以看到他的返回语句为:new String(0,len,buf);所以,替换的新字符串为新创建的字符串,并且创建以后改变了原来对象的指针。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值