A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王红霞 中级黑马   /  2012-7-10 03:46  /  2648 人查看  /  14 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 王红霞 于 2012-7-12 07:33 编辑

为什么这两个程序仅因为彩色部分不同 结果不同呢?

public class Demo3 {
    int a;
    int b;
    public void print_3() {
        a = 0;
        b = 0;
       int c =  0;
        g(b, c);
        System.out.println(a + ", " + b + ", " + c);
    }
    public void g(int b, int c) {
        a = 1;
        b = 2;
        c = 3;
    }
    public static void main(String args[]) {
        Demo3 d = new Demo3();
        d.print_3();
    }
}

输出结果是:1, 0, 0


public class Demo4 {
    int a;
    int b;
    public void print_4() {
        a = 0;
        b = 0;
       int[] c =  {0};
        g(b, c);
        System.out.println(a + ", " + b + ", " + c[0]);
    }
    public void g(int b, int[] c) {
        a = 1;
        b = 2;
       c[0] = 3;
    }
    public static void main(String args[]) {
        Demo4 d = new Demo4();
        d.print_4();
    }
}
输出结果是:1, 0, 3


评分

参与人数 1技术分 +1 收起 理由
蒋映辉 + 1

查看全部评分

14 个回复

倒序浏览
嗯 好厉害的局部变量问题 留个脚印 静待高手
回复 使用道具 举报
本帖最后由 贾存双 于 2012-7-10 07:26 编辑

public class Demo {
    int a;
    int b;
    public void print_4() {
        a = 0;
        b = 0;
       int c[] =  {0};
        g(b, c);
        System.out.println(a + ", " + b + ", " + c[0]);
    }
    public void g(int b, int d[]) { //这里我改为d好解释一点,d引用c的指向,指向c指向的堆内存。
        a = 1;
        b = 2;
       d[0] = 3; //这里的3本来应该存放在别的单元,假设是指向了d[1]位置,但这里却修改了所以修改了数组c[0]的值,并被保留下来,就像a=1被保留了下来。
    }
    public static void main(String args[]) {
        Demo3 d = new Demo3();
        d.print_4();
    }
}

数组在内存中的地址是连续的。对于上面的解释是我个人理解的不知道对不对,我是这么理解的。在Demo3的值没有被保留下来是因为在方法中断开了开始时的指向

评分

参与人数 1技术分 +1 收起 理由
刘笑 + 1 赞一个!

查看全部评分

回复 使用道具 举报
public class Demo3 {
    int a;
    int b;
    public void print_3() {
        a = 0;
        b = 0;
       int c =  0;
        g(b, c);
        System.out.println(a + ", " + b + ", " + c);
    }
    public void g(int b, int c) {
        a = 1;                              一个变量,如果在全局变量中被定义了一次,在局部变量中又被定义了一次,那么在一个方法中,会先去找局部变量,找到了
就操作局部变量,找不到才操作全局变量,我把这个理解为就近原则。然后这里b和c都被以参数的形式传递进来 是局部变量,改变值之没意义(方法调用结束就完了)a是全局变量,改变了要这个类消亡才会消亡  所以输出的时候是1

        b = 2;
        c = 3;
    }
回复 使用道具 举报
看这里:http://bbs.itheima.com/thread-18878-1-1.html,已经讲得很详细了
回复 使用道具 举报
public class Demo3 {
    int a;
    int b;  //定义了a和b两个成员变量
    public void print_3() {
        a = 0;
        b = 0;
       int c =  0;    //1、这里是定义了一个局部变量c
        g(b, c);     //2、调用了函数,但是,里面又重新定义了变量
        System.out.println(a + ", " + b + ", " + c);   //5、所以结果是1,0,0
    }
    public void g(int b, int c) {
        a = 1;    //3、a未重新定义过,就改变了调用这个函数的print_3函数的a值,
        b = 2;
        c = 3;      //4、这里重新定义了b和c,这个赋值就没有改变原来的值
    }
    public static void main(String args[]) {
        Demo3 d = new Demo3();
        d.print_3();
    }
}

评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1

查看全部评分

回复 使用道具 举报
public class Demo4 {
    int a;
    int b;
    public void print_4() {
        a = 0;
        b = 0;
       int[] c =  {0};
        g(b, c);
        System.out.println(a + ", " + b + ", " + c[0]);
    }
    public void g(int b, int[] c) {     这里的不同之处在于传入的只是这个数组的引用,而两个数组的引用是相同 的,指向的都是同一个存放数值的区域,所以结果改变了
        a = 1;
        b = 2;
       c[0] = 3;
    }
    public static void main(String args[]) {
        Demo4 d = new Demo4();
        d.print_4();
    }
}
回复 使用道具 举报
这个主要是参数传递的问题,参数传递类型主要有两种,一:值类型传递;二、引用类型传递。
1.按值传递
  适用范围:8种基本数据类型、String对象
  特点:在内存中复制一份数据,把复制后的数据传递到方法内部
  作用:在方法内部改变参数的值,外部数据不会跟着发生改变
2.按引用传递
  适用范围:数组、除String以外的其他所有类型的对象
  特点:将对象的地址传递到方法内部
  作用:在方法内部修改对象的内容,外部数据也会跟着发生改变
具体再说一下: 在第一个例子中,在第一个例子中是值传递,int c =  0;是一个整数类型,在内存中存放在堆内存中,它随着方法传递进方法体时,相当于这个整型变量在堆内存中又复制了一份,但是自身并没有改变,改变的只是自己的复制体。而在第二个例子中int[] c =  {0};是一个数组,它是引用类型传递。引用类型变量存储在对内存中,而引用所指向的对象则存放在栈内存中,引用变量随着方法传递进去时,其所指向的对象发生了变化。
这就是两个例子结果不同的原因,再遇到这样的问题建议从内存的角度考虑考虑。

回复 使用道具 举报
本帖最后由 achilles 于 2012-7-10 14:32 编辑


好激烈 是道好题
回复 使用道具 举报
孙新强 发表于 2012-7-10 11:13
这个主要是参数传递的问题,参数传递类型主要有两种,一:值类型传递;二、引用类型传递。
1.按值传递
   ...

Java中皆是按值传递的。详情见《Core Java》
回复 使用道具 举报
封明川 发表于 2012-7-10 09:04
public class Demo3 {
    int a;
    int b;  //定义了a和b两个成员变量

谢谢~我主要是第二个程序不大懂呢
回复 使用道具 举报
  1. public class Demo4 {
  2.     int a;
  3.     int b;
  4.     public void print_4() {
  5.         a = 0;
  6.         b = 0;
  7.        int[] c =  {0};  //定义了一个只有一个元素的int数组
  8.         g(b, c); // b,c为实参,局部变量,g(0,&c),c传的是数组首元素地址
  9.         System.out.println(a + ", " + b + ", " + c[0]);
  10.     }
  11.     public void g(int b, int[] c) {
  12.         a = 1;  // this.a = 1;
  13.         b = 2; // 局部变量b为2,若要改变Demo4的成员b的值,要用this.b = 2
  14.        c[0] = 3; // 数组c的首元素改为3,改变了元素的值
  15.     }
  16.     public static void main(String args[]) {
  17.         Demo4 d = new Demo4();
  18.         d.print_4();
  19.     }
  20. }
复制代码
回复 使用道具 举报
孙新强 发表于 2012-7-10 11:13
这个主要是参数传递的问题,参数传递类型主要有两种,一:值类型传递;二、引用类型传递。
1.按值传递
   ...

谢谢  讲的很详细
回复 使用道具 举报
本帖最后由 陆鹏 于 2012-7-12 08:11 编辑

下边。
回复 使用道具 举报
本帖最后由 陆鹏 于 2012-7-12 08:14 编辑

public class Demo3 {
    int a;
    int b;//这里定义了两个全局变量。    public void print_3() {
        a = 0;
        b = 0;
       int c =  0; //  c 是局部变量      
      g(b, c); //将全局变量b 和局部变量 c传入函数中。是传值传递。      
      System.out.println(a + ", " + b + ", " + c);
    }
    public void g(int b, int c) { ; /*注意,这里是传值传递,等于重新定义了变量,意识是说在内存中复制一份数据,把复制后的数据递到方法内部。在方法内部改变参数的值,外部数据不会跟着发生改变。而a是全局变量,没有传入函数中,对于a来说相当于调用函数将它改变了。
                    */
  
        a = 1      
       b = 2;
        c = 3;
    }
    public static void main(String args[]) {
        Demo3 d = new Demo3();
        d.print_3();
    }
}

输出结果是:1, 0, 0


public class Demo4 {
    int a;
    int b;
    public void print_4() {
        a = 0;
        b = 0;
       int[] c =  {0};
        g(b, c);
/*这里b同上,是传值传递,而c就不一样了,因为c相当于存的是一个地址,存的是数组角标为0的地址,所以相当于把地址传进 g函数中,把地址传入就是引用传递,其特点就是将对象的地址传递到方法内部然后在方法内部修改对象的内容,外部数据也会跟着发生改变。
这里一定要看懂,这就是关键。
*/
        System.out.println(a + ", " + b + ", " + c[0]);
    }
    public void g(int b, int[] c) {
        a = 1;
        b = 2;
       c[0] = 3;
    }
    public static void main(String args[]) {
        Demo4 d = new Demo4();
        d.print_4();
    }
}
输出结果是:1, 0, 3


回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马