黑马程序员技术交流社区

标题: 看视频时的一个小困惑?? [打印本页]

作者: 张庚    时间: 2013-2-3 15:19
标题: 看视频时的一个小困惑??
本帖最后由 张向辉 于 2013-2-5 12:22 编辑

//基本数据类型参数传递
class Demo
{
        public static void main(String[] args)
        {

                int x = 3;
                show(x);
                System.out.println("x="+x);
        }
        public static void show(int x)
        {
                x = 4;
        }
}

//引用数据类型参数传递
class Demo
{
        
        public static void main(String[] args)
        {
                String x="3";
                show(x);
                System.out.println("x="x);
        }
        public static void show(String  x)
        {
                x ="4";
        }
}

为什么上边那段代码运行打印结果是4
而下面这段打印时3    很费解??  
作者: 王溢君    时间: 2013-2-3 15:27
说明String类型数据,一旦定义,其内容是不变的,就是他的指向。
作者: 陈科宇    时间: 2013-2-3 15:31
呵呵,首先我要给你纠正一下,上面的会输出3,下面的代码才会输出4。
作者: 陈科宇    时间: 2013-2-3 15:43
     朋友,不好意思,我看错了。上下两段代码都会输出3,在学习引用类型的数据的参数传递时,不要使用String来使得自己糊涂。你稍等我一下。我一会儿贴出代码来讲解两者传递的差别。
作者: 张庚    时间: 2013-2-3 15:45
你越说我越糊涂了
作者: 张庚    时间: 2013-2-3 15:46
下面方法不是改变它的值了吗  怎么没用啊??
作者: 黑马陈涛    时间: 2013-2-3 15:54
上面的输出是3这个应该很好理解,下面主要说一下String类型的存储,例如我们定义一个String s="3",这里的s存在栈内存中而在堆中建立了一个String的对象存放数据“3”,然后把数据的地址0x0012赋给栈中的s。当show()使用的时候也是向函数传递的是0x0012这个地址值,也就是在操作同一个对象,当函数将值改为“4”时,堆中的数据自然也就变成了“4”,打印出的值也就是“4”。
(不太会插入图片这里上传成附件,希望这个草图对你有帮助)

demo.png (15.5 KB, 下载次数: 47)

demo.png

作者: 陈科宇    时间: 2013-2-3 16:01
class Student {
        int age;
        String name;
    public Student(int age,String name)
    {
            this.age=age;
            this.name=name;
    }
}

public class Demo {
        // 基本数据类型参数传递
        public static void changeJiBen(int x) {
                x = 520;
        }
        //引用数据类型参数传递
        public static void changeYinYong(Student s) {
                s.age=101;
        }

        public static void main(String[] args) {
                int x = 250;
                Student s=new Student(23,"Keyee");
                changeJiBen(x);
                changeYinYong(s);
                System.out.println("x=" + x);
                System.out.println("s.age=" + s.age);

        }
    /*
     * 我们可以看到输出x=250,s.age=101。其实只要搞清楚了传递参数的
     * 规则,就不难理解。在主函数中调用changeJiBen时,并没有把存放
     * 在main方法栈区的x的地址传递给changeJiBen的形参,而是传递了
     * 250这个整数值,也就是一旦调用了该方法,形参整数的值就变为250。
     * 而这个形参存放在changeJiBen的方法栈区内,如果在改变其值,与
     * main方法里的x不会有任何关系。那为什么传递Student这个引用对象
     * 却能修改呢。这就很有趣了。在main方法里建立了Student对象后,引
     * 用对象s存放在main栈区里,s并没有存放实际的数据,它是一个指针。
     * 它指向了堆内存里的实际的Student对象,这个对象存放了age=23,
     * name="Keyee"。在调用changeYinYong时,形参得到的是实际对象
     * 在堆内存的地址,也就是形参和main里的s指向了同一块堆内存,两个
     * 方法操作同一份数据,当然可以看到其改变。
     * 本来应该上图的,时间有点仓促。不知这样讲,是否够详细。如果不详
     * 细,我再整理一下。把图也画出来,写成日志。顺便也解释一下你传递
     * String的疑惑。
     *
     */
}
作者: 陈科宇    时间: 2013-2-3 16:06
我的楼上就提供了很好地解释方法。传递参数一块儿,不仅要看视频,还要看书。书中配有参数传递中的图解。c语言和java的较好的书籍,都会画一定的篇幅来讲解参数传递,例如这一块我推荐看看李刚的《疯狂java讲义》,对这个知识点有很详细的图解,认真看后就会很好地理解。
作者: 陈科宇    时间: 2013-2-3 16:12
我感觉讲得还不够透彻清晰,我会专门写成日志,和大家交流交流。
作者: 黄锦成    时间: 2013-2-3 16:52
你参考一下这位师兄的http://bbs.itheima.com/thread-36998-1-1.html
作者: 王昕    时间: 2013-2-3 19:36
Java是按值传递的,传递的是字节拷贝。形参的生存范围只在方法体里。你把形参和实参搞成一样的名字迷惑自己,他俩名字看着一样,但是是两个变量。
对象引用就像对象的遥控器,“.”操作符就像按下遥控器的按钮。
第一个例子,你的形参叫 x 还是叫 y 没有任何区别,都只是把实参的值 3 拷贝一份给形参。就像你拷了我的作业,你在你拷的作业上修改,影响不到我的作业。
第二个例子,x 是一个遥控 string 类型的遥控器,形参 x 是另一个遥控器,你调用方法show()的时候,让一个遥控器也指向了另一个遥控器的遥控对象,但是,你的 x = "4","4"是一个新电视,你只是让形参遥控器 x 又指向了新电视而已,没有“.”运算符你就没有按下遥控器的按钮,也就无法遥控第一个电视了。




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