关于字符串数组的值的问题

a1411473204 2017-09-07 05:19:43
Map<String,String[]> testMap=new HashMap<String, String[]>();
String str[]= {"abc","cddd","ddd","sjei"};
String str1[]= {"时间覅饿","少女风打开","降低风"};
testMap.put("英文", str);
testMap.put("中文", str1);
for(String value:testMap.keySet())
{
String values[]=testMap.get(value);
for(int i=0;i<values.length;i++)
{
try {
values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
for(String key:testMap.keySet())
{
String values[]=testMap.get(key);
System.out.println(key+": ");
for(int i=0;i<values.length;i++)
{
System.out.println(values[i]);
}
}
当map的值是String数组时,将键值赋给另外一个数组引用,然后遍历修改map的值,但是原来的map的键的值也变了,不是改变了引用而已吗?为什么可以改变该引用指向的内容
Map<String,String> testMap=new HashMap<String,String>();
String str1="今天";
String str2="today";
testMap.put("中文", str1);
testMap.put("英文", str2);
for(String key:testMap.keySet())
{
String str=testMap.get(key);
try {
str=new String(str.getBytes("utf-8"),"iso-8859-1");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for(String key:testMap.keySet())
{
System.out.println(key+": "+testMap.get(key));

}
}
当map的键为字符串时,结果却和上面的相反,只是改变了引用指向的对象,但是原来的内容没变,是因为String数组的引用一旦赋值后引用就不能改变指向的对象了吗?为什么?求解答
...全文
528 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
a1411473204 2017-09-18
  • 打赏
  • 举报
回复
引用 16 楼 a1411473204 的回复:
[quote=引用 14 楼 miaoch 的回复:] 你重新get的话 引用还是那个引用, 但是数组里的元素引用改变了,
为什么引用的会没变[/quote]为什么数组的引用不会断,我之前一直想搞明白这个
a1411473204 2017-09-18
  • 打赏
  • 举报
回复
引用 14 楼 miaoch 的回复:
你重新get的话 引用还是那个引用, 但是数组里的元素引用改变了,
为什么引用的会没变
  • 打赏
  • 举报
回复
引用 13 楼 a1411473204 的回复:
values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");我这里不也是对数组中的每个元素进行new吗,也就是按常理来说数组中每个元素都关联了新的对象啊,为什么它就改变了原来的值呢

map和values指向的都是这个数组对象(即都指向同一地址),只是它里面装的东西变了。你去再get获得的还是这个数组对象,只是里面装的东西被你之前改了。
miaoch 2017-09-18
  • 打赏
  • 举报
回复

你重新get的话 引用还是那个引用,
但是数组里的元素引用改变了,
a1411473204 2017-09-18
  • 打赏
  • 举报
回复
引用 12 楼 qq_33140971 的回复:
[quote=引用 11 楼 a1411473204 的回复:] 但是为什么String会指向一个新的对象,而数组却能修改指向对象的值呢
你首先要知道所谓的赋值语句到底干了什么,对于引用数据类型来说: 它是把让“=”后面的对象的地址关联到前面的引用。 对于map来说你没法获得它value的引用,所以你是改不了它的值的(除非你用put()让它自己去改变),所以说map里的这个引用所指向的地址都没变。 但是你可以去获取它的地址(get())然后把它关联到一个新的引用上
String  values[]=testMap.get(value);
, 然后你for循环是通过values这个引用对这个数组里的元素进行操作的,因为values和map里的这个value都指向的是同一个地址,所以map里的数组也改变了。 但是你的第二个方法里
String str=testMap.get(key);
把map里的字符串关联到了str这个引用上,然后你这个操作
str=new String(str.getBytes("utf-8"),"iso-8859-1");
是重新new了一个对象并把它关联到了这个str引用上,所以对于map是没什么影响的。 刚学Java的新手在没完全弄懂OOP之前,遇到不了解关于赋值方面的问题,要学会画内存图,了解他每一步干了什么[/quote] values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");我这里不也是对数组中的每个元素进行new吗,也就是按常理来说数组中每个元素都关联了新的对象啊,为什么它就改变了原来的值呢
  • 打赏
  • 举报
回复
引用 11 楼 a1411473204 的回复:
但是为什么String会指向一个新的对象,而数组却能修改指向对象的值呢
你首先要知道所谓的赋值语句到底干了什么,对于引用数据类型来说: 它是把让“=”后面的对象的地址关联到前面的引用。 对于map来说你没法获得它value的引用,所以你是改不了它的值的(除非你用put()让它自己去改变),所以说map里的这个引用所指向的地址都没变。 但是你可以去获取它的地址(get())然后把它关联到一个新的引用上
String  values[]=testMap.get(value);
, 然后你for循环是通过values这个引用对这个数组里的元素进行操作的,因为values和map里的这个value都指向的是同一个地址,所以map里的数组也改变了。 但是你的第二个方法里
String str=testMap.get(key);
把map里的字符串关联到了str这个引用上,然后你这个操作
str=new String(str.getBytes("utf-8"),"iso-8859-1");
是重新new了一个对象并把它关联到了这个str引用上,所以对于map是没什么影响的。 刚学Java的新手在没完全弄懂OOP之前,遇到不了解关于赋值方面的问题,要学会画内存图,了解他每一步干了什么
  • 打赏
  • 举报
回复
miaoch 2017-09-18
  • 打赏
  • 举报
回复
for(String value:testMap.keySet()) 首先你要知道这句话 只是遍历keySet,然后value只会是原来的一个引用拷贝。 就类似,String s = new String("1"); String value = s; s是Map中真正存放的引用值,而你拥有的至少一份拷贝而已。 倘若你改变了value,即 value = new String("2"); 合起来就是 String s = new String("1"); String value = s; value = new String("2"); 那你说s有变化么。 而map中存的是s。所以你下次再for(String value:testMap.keySet()) 不过是 String value2 = s; 那么value2 依旧是原来的1 String s = new String("1"); String value = s; value = new String("2"); String value2 = s; System.out.println(s); System.out.println(value); System.out.println(value2); 你可以试试
a1411473204 2017-09-17
  • 打赏
  • 举报
回复
引用 10 楼 qq_33140971 的回复:
map的get方法是去获取key所对应的的value的引用所对应的地址,除非你去put()这个key所对应的的value的引用所对应的地址就不会改变。 所以实际上你上面两个问题中map的value无论是String[]还是String的地址都没改变。 但是你的第一个问题中,获取了String[]的地址,然后改变了这个数组中的几个值。 就相当于你拿到了一个装了汽水的饮料瓶,你把里面的汽水喝完了,但是向里面撒了一泡尿,但是瓶子还是那个瓶子
但是为什么String会指向一个新的对象,而数组却能修改指向对象的值呢
  • 打赏
  • 举报
回复
map的get方法是去获取key所对应的的value的引用所对应的地址,除非你去put()这个key所对应的的value的引用所对应的地址就不会改变。 所以实际上你上面两个问题中map的value无论是String[]还是String的地址都没改变。 但是你的第一个问题中,获取了String[]的地址,然后改变了这个数组中的几个值。 就相当于你拿到了一个装了汽水的饮料瓶,你把里面的汽水喝完了,但是向里面撒了一泡尿,但是瓶子还是那个瓶子
yyfhz 2017-09-13
  • 打赏
  • 举报
回复
Case2里面的这句话写错了 //从效果上来看,好像是修改了数组变量里的值,不会导致另一个数组变量发生了同步变动,只要它们一开始指的是同一个数组。 应该是 //从效果上来看,好像是修改了数组变量里的值,导致了另一个数组变量发生了同步变动,只要它们一开始指的是同一个数组。
yyfhz 2017-09-13
  • 打赏
  • 举报
回复
引用 7 楼 a1411473204 的回复:
[quote=引用 5 楼 yyfhz 的回复:] 对于java,大致可以这么理解:java中所有的对象的传递都是引用传递(即地址传递),所以你若修改了某块内存地址,会导致所有指向它的变量读取值发生变化。 另外,对于一些"基本"的数据类型如int, Integer, Boolean, bool, String, Date之类的,他们的每次赋值都会创建一个“新"对象并修改指定的变量使他指向那个"新"”对象,因此其它那些指向"老"对象的变量的值并未随之变动。
但是你这句话不太适合这个场景,两个都是引用指向一个新对象,但是复制的数组那里改变了,原来的数组的值也改变了,,但是下面那个的原值却没变[/quote] 给友2个Case来看看吧~~ Case1,String类型的赋值和变化。 牢牢记住,Java中所有的东西都是”地址”,所有的变量赋值都等价于修改其地址指针。

String str1 = "Hello" ; //这里创建了一个字符串对象,假设其地址是00001,这个地址中存放了"Hello"字符串,而变量str1中"实际"存放的是地址00001。
String str2 = str1;  //通过将str2赋值为str1的地址,这里变量str2中"实际"存放的就是地址00001,因此如果答应一下str2中的内容,出来的就是"Hello"
str2 = "Goodbye"  //这里创建了一个新的字符串对象(注意到前面所说的,对于String内容的修改会导致创建新的String对象),假设其地址是00002,这个地址中放了"Goodbye"字符串,而后将地址00002赋值给变量str2.
//想一想,程序运行到此时两个变量的内容  -- str1还是存放地址00001,而str2中的地址已经是00002了,因此当我们打印这两个变量的时候...
System.out.println(str1);  //这里打印出来的是地址00001的内容,即"Hello"
System.out.println(str2);  //这里打印出来的是地址00002的内容,即"Goodbye"

//从效果上来看,好像是修改了字符串变量里的值,不会导致另一个字符串变量发生同步变动,哪怕一开始这两个字符串变量是相同的。
Case2,然后我们看看,当修改的内容是数组时会怎么样,同样的牢牢记住,Java中所有的东西都是”地址”,所有的变量赋值都等价于修改其地址指针。

String[] ary1= {"Hello"};  
//上句创建了一个字符串对象其内容为"Hello"假设其地址为00001。另外创建了一个数组对象,假设其地址是ARY01,里面存放的是每个元素的”地址“。
//显然,现在只有一个元素,其值为地址00001,因此可以认为 变量ary1的值是地址ARY01,然后内存ARY01里存放的内容是00001,而最后在地址00001里的内容是字符串"Hello"。

//这么简单的一个java语句,可以理解为java系统是如此来访问到a[0]中的值的:
//先查变量ary1,发现他存放的是地址ARY01,然后飞奔到ARY01去找里面的首元素,发现是00001,再跳到00001去看,终于发现是字符串"Hello"了。
System.out.println(ary1[0]);  

String [] ary2= ary1; //通过这样的赋值,变量ary2里存放的是地址ARY01,因此基于同样的道理
System.out.println(ary2[0]); //这句话打印出来的也是Hello,于是我们说ary2和ary1里面的内容一样。

//下面开始修改数组元素的内容,记住,数组并非是前面所说的“简单”数据类型,因此对它的修改不会导致java创建一个新数组。

ary2[0]="Goodbye";  //这里创建了一个新的字符串对象(注意到前面所说的,对于String内容的修改会导致创建新的String对象),假设其地址是00002,这个地址中放了"Goodbye"字符串,而后将地址00002赋值给ary2[0]。
.
//想一想,这里的ary2[0]到底是什么
//..
//...
//首先,ary2变量本身的地址是没有发生改变(因为对数组本身的修改不会创建新数组),还是ARY01 (这是关键!!!)
//然后,这个ARY01里面的内容,原本存放的是地址00001的,现在变成00002了。于是
System.out.println(ary2[0]);  //这里,java通过ary2 => ARY01 =>00002 =>的途径,搜索到了"Goodbye"

//那么对于ary1变量呢?想一想, ary1里面存放的是什么?也是地址ARY01,因此
System.out.println(ary1[0]); //这里,java通过ary1 => ARY01 =>00002 =>的途径,搜索到了"Goodbye" 

//从效果上来看,好像是修改了数组变量里的值,不会导致另一个数组变量发生了同步变动,只要它们一开始指的是同一个数组。

看吧,并没有特别神奇的地方,只是对于"简单"数据而言,java是拒绝对它直接进行改动的,它宁愿创建一个新的数据对象。 而对"复杂"的数据而言,java就不管那么多了,它允许我们队里面的内容进行直接的修改。
a1411473204 2017-09-12
  • 打赏
  • 举报
回复
引用 5 楼 yyfhz 的回复:
对于java,大致可以这么理解:java中所有的对象的传递都是引用传递(即地址传递),所以你若修改了某块内存地址,会导致所有指向它的变量读取值发生变化。 另外,对于一些"基本"的数据类型如int, Integer, Boolean, bool, String, Date之类的,他们的每次赋值都会创建一个“新"对象并修改指定的变量使他指向那个"新"”对象,因此其它那些指向"老"对象的变量的值并未随之变动。
但是你这句话不太适合这个场景,两个都是引用指向一个新对象,但是复制的数组那里改变了,原来的数组的值也改变了,,但是下面那个的原值却没变
李德胜1995 2017-09-08
  • 打赏
  • 举报
回复
引用 3 楼 a1411473204的回复:
[quote=引用 2 楼 pany1209 的回复:]

第一个:
String  values[]=testMap.get(value);//values指向Map集合的两个Key的两个value的地址
values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");//对内容直接进行修改
第二个:
String str=testMap.get(key);//str指向两个value的地址
str=new String(str.getBytes("utf-8"),"iso-8859-1");//没有进行修改,直接重新指向一个新创建的string对象
为什么下面没有修改而是重新指向一个对象呢?关键是这里,原理是什么[/quote] 下面那行代码修改了???
a1411473204 2017-09-08
  • 打赏
  • 举报
回复
引用 2 楼 pany1209 的回复:

第一个:
String  values[]=testMap.get(value);//values指向Map集合的两个Key的两个value的地址
values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");//对内容直接进行修改
第二个:
String str=testMap.get(key);//str指向两个value的地址
str=new String(str.getBytes("utf-8"),"iso-8859-1");//没有进行修改,直接重新指向一个新创建的string对象
为什么下面没有修改而是重新指向一个对象呢?关键是这里,原理是什么
「已注销」 2017-09-08
  • 打赏
  • 举报
回复
// 这是你的原话:
第一个:
String[] values = testMap.get(value);
values[i] = new String(values[i].getBytes("utf-8"),"iso-8859-1");
第二个:
String str = testMap.get(key);
str = new String(str.getBytes("utf-8"),"iso-8859-1");
values 是一个数组的引用,指向的对象里面存放了一组元素:字符串引用。而 str 只是一个字符串引用。 对 values[i] 赋值,其实是将元素 i 的引用指向了一个新的字符串对象,并不是把值修改了。 第一个,你没对 values 重新赋值,它引用的还是那个数组。你赋值的是数组元素,即元素指向的引用对象变化了而已。 第二个,你对 str 重新赋值,它引用的字符串已经变了,之前的如果你没有记录,那就没法再次使用了。 包括 Map、List 同理。
yyfhz 2017-09-08
  • 打赏
  • 举报
回复
对于java,大致可以这么理解:java中所有的对象的传递都是引用传递(即地址传递),所以你若修改了某块内存地址,会导致所有指向它的变量读取值发生变化。 另外,对于一些"基本"的数据类型如int, Integer, Boolean, bool, String, Date之类的,他们的每次赋值都会创建一个“新"对象并修改指定的变量使他指向那个"新"”对象,因此其它那些指向"老"对象的变量的值并未随之变动。
李德胜1995 2017-09-07
  • 打赏
  • 举报
回复

第一个:
String  values[]=testMap.get(value);//values指向Map集合的两个Key的两个value的地址
values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");//对内容直接进行修改
第二个:
String str=testMap.get(key);//str指向两个value的地址
str=new String(str.getBytes("utf-8"),"iso-8859-1");//没有进行修改,直接重新指向一个新创建的string对象
  • 打赏
  • 举报
回复
先自己画图解决试试,不会@ 我

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧