黑马程序员技术交流社区

标题: String 问题 郁闷 [打印本页]

作者: 唐凯    时间: 2011-8-6 21:16
标题: String 问题 郁闷
[code=java]public class Test{
public static void changestr(String str){
str = "heima";
}
public static void main(String []args)
{
String str = "2011";
changestr(str);
System.out.println(str);
}
}[/code]这里的结果是2011,这是问什么?
作者: 匿名    时间: 2011-8-6 23:36
你再main 方法里面 这样String  str1 =  changestr(str); 然后打印 str1 试试  我认为你打印的时候 打的不是changestr 方法调用之后的结果 而是main 方法里面定义的那个str
作者: 匿名    时间: 2011-8-7 00:19
因为changestr方法结束后,在栈中分配的内存就会消失,所以打印出来的还是“20 11”,建议还是去看看内存分配那方面的知识
作者: 匿名    时间: 2011-8-7 00:34
[code=java]public class Test {

        public static String  changestr(String str){
                return str="heima";
        }

        public static void main(String[] args) {
                // TODO Auto-generated method stub

                String str = "2011";

                String a = changestr(str);

                System.out.println(a);
               
        
        }

}[/code]System.out.println(str);输出的str是main方法中的str
在changestr方法中你没有设置返回值,设置返回值之后在main方法中调用
作者: 匿名    时间: 2011-8-7 00:36
我们应该要知道一点:[color=Red]Java方法里面的参数传递方式只有一种:值传递---就是将实际参数值的副本(复制品)传入方法内,而参数本身是不会收到任何影响[/color]

[color=Red]java中方法的参数传递为值传递,不管这个参数是基本类型还是引用类型,我们传递过去的都是该值的一个副本,这个副本作为方法的局部变量保存在栈(stack)中[/color]

分析执行上面程序的步骤:
1、上述在运行main方法的时候,main方法的栈区保存了一个str的变量,
2、当执行changestr方法的时候,系统进入changestr方法,将main方法里面的变量作为参数传递到这个方法里面(是副本),这个时候是changestr方法的栈区,---注:上面两个方法都是栈内存中的
3、这个时候系统存在两个栈区main方法和changestr方法,分别保存他们的局部变量,main方法str作为参数传递到changestr方法,但是changestr方法栈区产生变量str,并且讲main方法的str变量赋值给changestr方法栈区的str参数(这个就是对形参进行初始化),且系统存在两个str变量,只不过存在不同的方法栈区
4、程序在changestr方法改变str变量的时候,就是在changestr方法栈区里面进行重新赋值,结束再输出str的值。

5、从上面我们可以知道main方法栈区的str变量没有任何改变,程序只是改变了changestr方法栈区的str变量的值,这就是值传递的本质,系统开始执行方法的时候,系统为形参执行初始化,就是把实参变量的值付给方法的形参变量,方法里面的操作并不是实际的实参变量。

总结:[color=Red]最后对于引用类型的参数的传递,一样也是采用的值的传递方式,唯一的不同点就是,他们和基本类型的变量在内存里面的保存方式不同,引用类型的变量保存的是对象的引用,当把这个引用的值传给其他变量的时候,其他变量也就指向了实际的对象,当操作这个对象的时候就是对实际的对象的操作,它是通过引用来直接关联对象的,传递的不是直接的对象,而是指向这个对象的引用,各位麻油可以自己画图试试 [/color]

如下程序:[code=java]package cn.itcast.heima
public class TestPrimitiveTransfer
{
        public static void swap(int a , int b)
        {
                //下面三行代码实现a、b变量的值交换。
                //定义一个临时变量来保存a变量的值
                int tmp = a;
                //把b的值赋给a
                a = b;
                //把临时变量tmp的值赋给a
                b = tmp;
                System.out.println("swap方法里,a的值是" + a + ";b的值是" + b);
        }
        public static void main(String[] args)
        {
                int a = 5;
                int b = 6;
                swap(a , b);
                System.out.println("交换结束后,实参a的值是" + a + ";实参b的值是" + b);
        }
}[/code]运行结果可以看到:[code=java]swap方法里,a的值是6;b的值是5
交换结束后,实参a的值是5;实参b的值是6[/code]--------------------------------------------
从上面可以看到Java方法参数的传递机制:[color=Red]值传递---就是将实际参数值的副本(复制品)传入方法内,而参数本身是不会收到任何影响[/color]
可以参考这个帖子[url]http://bbs.itheima.com/thread-607-1-1.html[/url]
作者: 匿名    时间: 2011-8-7 03:09
正如楼上说的==值传递
作者: 赵侃    时间: 2011-8-7 04:49
我记得一位老师说过,这个问题是因为String的对象是常量,比如:
String a = “ab”;
内存常量池中会创建一个"ab",此时
a = "ab" + "c";
常量池中就会创建一个"abc",而之前的"ab"依然存在,不会被改变,改变的是变量a所指向的地址。
传参时如果传入的是一个普通的对象,我们改变他的某个属性,比如说改变了name,那么通过任何指向此对象的变量访问这个对象,它的name都是改变后的值,因为内存中已经不存在改变前的值了。
但是String不一样,如果你通过某个指向String对象的变量改变它的值,那么你实际改变的是这个变量所指向的地址,而没有改变String对象本身,所以changestr方法里的str,和main方法里的str,在执行str = "heima";之前,指向同一个地址,执行之后,已经指向不同的地址了。而如果传的是普通的对象,无论你怎么改这个对象,两个str指向的地址都是一样的。
作者: 匿名    时间: 2011-8-7 07:20
标题: 参数传递
基本数据类型的参数传递

    public class PassParamOne
{
   public static void main(String[] args)
  {
      int x=5;
       change(x);
      System.out.print(x);
  }
   public static void change(int x)
   {
      x=3 ;
     }
}           
  输出结果为5,main() 方法中X的值被放入change()方法中,随后change 方法的X被改变,
   change结束后X被释放,但是 主函数的 X始终没有被改变。                                       


引用数据类型的参数传递

  public class PassParam
{
        int y;  
  public static void main(String[] args)
       {               
        PassParam pa=new PassParam();            
            pa.y=1;   
          change(pa);
          System.out.println(pa.y);  
         
         int []x=new int[10];              //数组
            x[0]=5;
             change(x);
           System.out.println(x[0]);         
       }
  public static void change(PassParam pa)
   {   
         pa.y=4;
    }   
    public static void change(int[] x)
   {   
       x[0]=3;
    }   
}                  
  输出结果:4   对象的引用变量作为参数传递,两个方法指向同一个堆内存,
  change()方法改变了堆内存的值,被释放后 主函数指向的内容也已被改变。
  传递数组变量 和 传递引用变量的意义是一样的
作者: 匿名    时间: 2011-8-7 21:29
可以看看张老师基础视频中面向对象上中介绍的 函数的参数传递部分,分为基本数据类型和引用参数的传递,介绍的很仔细。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2