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数组的引用一旦赋值后引用就不能改变指向的对象了吗?为什么?求解答

解决方案 »

  1.   


    第一个:
    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对象
      

  2.   

    对于java,大致可以这么理解:java中所有的对象的传递都是引用传递(即地址传递),所以你若修改了某块内存地址,会导致所有指向它的变量读取值发生变化。
    另外,对于一些"基本"的数据类型如int, Integer, Boolean, bool, String, Date之类的,他们的每次赋值都会创建一个“新"对象并修改指定的变量使他指向那个"新"”对象,因此其它那些指向"老"对象的变量的值并未随之变动。
      

  3.   

    // 这是你的原话:
    第一个:
    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 同理。
      

  4.   

    但是你这句话不太适合这个场景,两个都是引用指向一个新对象,但是复制的数组那里改变了,原来的数组的值也改变了,,但是下面那个的原值却没变
    给友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就不管那么多了,它允许我们队里面的内容进行直接的修改。
      

  5.   

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

  6.   

    map的get方法是去获取key所对应的的value的引用所对应的地址,除非你去put()这个key所对应的的value的引用所对应的地址就不会改变。
    所以实际上你上面两个问题中map的value无论是String[]还是String的地址都没改变。
    但是你的第一个问题中,获取了String[]的地址,然后改变了这个数组中的几个值。
    就相当于你拿到了一个装了汽水的饮料瓶,你把里面的汽水喝完了,但是向里面撒了一泡尿,但是瓶子还是那个瓶子
      

  7.   

    但是为什么String会指向一个新的对象,而数组却能修改指向对象的值呢
      

  8.   

    你首先要知道所谓的赋值语句到底干了什么,对于引用数据类型来说:
    它是把让“=”后面的对象的地址关联到前面的引用。
    对于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之前,遇到不了解关于赋值方面的问题,要学会画内存图,了解他每一步干了什么
      

  9.   

    你首先要知道所谓的赋值语句到底干了什么,对于引用数据类型来说:
    它是把让“=”后面的对象的地址关联到前面的引用。
    对于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之前,遇到不了解关于赋值方面的问题,要学会画内存图,了解他每一步干了什么
    values[i]=new String(values[i].getBytes("utf-8"),"iso-8859-1");我这里不也是对数组中的每个元素进行new吗,也就是按常理来说数组中每个元素都关联了新的对象啊,为什么它就改变了原来的值呢
      

  10.   


    你重新get的话 引用还是那个引用,
    但是数组里的元素引用改变了,
      

  11.   

    map和values指向的都是这个数组对象(即都指向同一地址),只是它里面装的东西变了。你去再get获得的还是这个数组对象,只是里面装的东西被你之前改了。
      

  12.   

    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);
    你可以试试