https://blog.csdn.net/fenglllle/article/details/81389286
原因是方法在执行的时候有栈帧的概念,入栈的时候只是压栈方法参数是传入参数的副本。
JVM高级特性
此时区分数据类型:基本类型和引用类型
基本类型:值存放在局部变量表中,无论如何修改只会修改当前栈帧的值,方法执行结束对方法外不会做任何改变;此时需要改变外层的变量,必须返回主动赋值。
引用数据类型:指针存放在局部变量表中,调用方法的时候,副本引用压栈,赋值仅改变副本的引用。但是如果直接改变副本引用的值,修改了引用地址的对象,此时方法以外的引用此地址对象当然被修改。(两个引用,同一个地址,任何修改行为2个引用同时生效)
@RequestMapping(value = "/ttt/{id}")
public String ttt(@PathVariable("id") Long id)
{
//查询商品基本信息
GoodInfoBean goodInfoBean = new GoodInfoBean();
System.out.println("111============="+goodInfoBean.hashCode());
GoodInfoBean gg = test(goodInfoBean, id);
System.out.println("222============="+goodInfoBean.hashCode());
System.out.println("333=============gg="+gg.hashCode());
System.out.println("ggg============="+goodInfoBean);
return "ddd";
}
public GoodInfoBean test(GoodInfoBean gg,Long id){
System.out.println("2-111============="+gg.hashCode());
gg.setId(222L);//修改后,GoodInfoBean的hashCode就会变动了!!!
gg = goodInfoJPA.findOne(id);
gg.setId(333L);
System.out.println("2-222============="+gg.hashCode());
System.out.println("2-333============="+gg);
return gg;
}
111=============1244802162
2-111=============1244802162
Hibernate:
select
goodinfobe0_.tg_id as tg_id1_0_0_,
goodinfobe0_.tg_order as tg_order2_0_0_,
goodinfobe0_.tg_price as tg_price3_0_0_,
goodinfobe0_.tg_title as tg_title4_0_0_,
goodinfobe0_.tg_type_id as tg_type_5_0_0_
from
good_infos goodinfobe0_
where
goodinfobe0_.tg_id=?
2-222=============472670822
2-333=============GoodInfoBean(id=333, title=芹菜, price=12.4, order=1, typeId=1)
222=============-881157515
333=============gg=472670822
ggg=============GoodInfoBean(id=222, title=null, price=0.0, order=0, typeId=null)
关于String,本质是final类型char数组,不可修改,只能赋值,在做参数传入方法修改时,其实是新建对象,必须返回重新对外面的变量赋值才会对外面的String引用生效。
看String源码的任意一个方法即可明白
引用类型会引起浅拷贝和深拷贝现象。
测试代码:
public static void setValue(StringBuilder str){
str = new StringBuilder("sss");
}
public static void setValue2(StringBuilder str){
str.append("sss");
}
public static void main(String[] args) {
StringBuilder str = new StringBuilder();
System.out.println("1==="+str.hashCode());
setValue(str);
System.out.println("2==="+str.hashCode());
System.out.println(str.toString()); //输出空字符串
setValue2(str);
System.out.println("3==="+str.hashCode());
System.out.println(str.toString()); //输出sss
String a="111";
System.out.println(a.hashCode());
a="222";
System.out.println(a.hashCode());
}
1===1607521710 2===1607521710
3===1607521710 sss 48657 49650 string源码: /** * Returns a string resulting from replacing all occurrences of * {@code oldChar} in this string with {@code newChar}. *
* If the character {@code oldChar} does not occur in the * character sequence represented by this {@code String} object, * then a reference to this {@code String} object is returned. * Otherwise, a {@code String} object is returned that * represents a character sequence identical to the character sequence * represented by this {@code String} object, except that every * occurrence of {@code oldChar} is replaced by an occurrence * of {@code newChar}. *
* Examples: *
* * @param oldChar the old character. * @param newChar the new character. * @return a string derived from this string by replacing every * occurrence of {@code oldChar} with {@code newChar}. / public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; / avoid getfield opcode */* "mesquite in your cellar".replace('e', 'o') * returns "mosquito in your collar" * "the war of baronets".replace('r', 'y') * returns "the way of bayonets" * "sparring with a purple porpoise".replace('p', 't') * returns "starring with a turtle tortoise" * "JonL".replace('q', 'x') returns "JonL" (no change) *
while (++i < len) {
if (val[i] == oldChar) {
break;
}
}
if (i < len) {
char buf[] = new char[len];
for (int j = 0; j < i; j++) {
buf[j] = val[j];
}
while (i < len) {
char c = val[i];
buf[i] = (c == oldChar) ? newChar : c;
i++;
}
//String的value 是final char[],一旦创建不能改变
return new String(buf, true);
}
}
return this;
}