黑马程序员技术交流社区

标题: a+=b的问题 [打印本页]

作者: 熊猫86    时间: 2013-12-9 14:48
标题: a+=b的问题


  1. public class Test {
  2.         public static void leftshift(int a, int b) {
  3.                    a+=b;
  4.         }
  5.         public static void main(String args[]) {
  6.                 int a = 5, b = 2;
  7.                 leftshift(a, b);
  8.                 System.out.println(a);
  9.         }
  10. }
复制代码


有点晕,这个代码运行的结果为啥是5啊?
如果用a+=b;直接替换leftshift(a,b);则结果为7,这两者区别是什么?
作者: 李然    时间: 2013-12-9 15:28
调用leftshift(a, b),输出a是5因为在题中也就是把5和2这两个值传给调用的函数leftshift(),但是main函数里的a和b的值未发生变化,leftshift函数里计算的只是形参的值,并没有改变a,b本身的值,所以最后输出的i的值还是a本身的值5。
换成a+=b,再输出a的值是7的原因是,a+=b相当于是a = a + b,就是将a,b的和加算之后又赋给了a,所以a的值自然就变成了7.
如果不明白的话,您可以继续追问。
作者: 王尧    时间: 2013-12-9 15:36
本帖最后由 王尧 于 2013-12-9 15:38 编辑

楼上说的很清楚了,如果你想得到7可以把代码修改成酱紫:
  1. public class Test {
  2.         public static int leftshift(int a, int b) {
  3.                    a+=b;
  4.                   return a;
  5.         }
  6.         public static void main(String args[]) {
  7.                 int a = 5, b = 2;
  8.                 int c=leftshift(a, b);
  9.                 System.out.println(c);
  10.         }
  11. }
复制代码

作者: 熊猫86    时间: 2013-12-9 16:26
李然 发表于 2013-12-9 15:28
调用leftshift(a, b),输出a是5因为在题中也就是把5和2这两个值传给调用的函数leftshift(),但是main函数里 ...

为什么上个函数调用的是两个形参,而下面的数组就可以用函数直接操作呢,为什么数组这个改变的不是形参呢?
  1. public class Demo {
  2.        
  3.         public static void main(String args[]) {
  4.                                
  5.                 int[] arr= new int[]{1,2};
  6.                 swap(arr);
  7.                 System.out.println(arr[0]);
  8.                
  9.         }
  10.        
  11.         public static void swap (int[] arr) {
  12.                 int temp = arr[0];
  13.                 arr[0] = arr[1];
  14.                 arr[1] = temp;
  15.         }
  16. }
复制代码

输出结果为2,达到了交换目的
作者: 熊猫86    时间: 2013-12-9 16:28
王尧 发表于 2013-12-9 15:36
楼上说的很清楚了,如果你想得到7可以把代码修改成酱紫:

同上,麻烦请教下怎么确定上个是形参,而数组这个就是实参,谢谢
作者: 王新年    时间: 2013-12-9 16:36
原因是leftshift(int a, int b)方法中操作的是局部变量即方法中的参数a和b ,该变量和main()方法中的a和b不是同一个,所以在leftshift(int a, int b)方法中操作后对main()中的a和b没有影响!
但是如果使用a+=b来替换leftshift(int a, int b)方法就相当于在main()方法中来操作a和b 所以a的值是7
作者: 熊猫86    时间: 2013-12-9 16:41
王新年 发表于 2013-12-9 16:36
原因是leftshift(int a, int b)方法中操作的是局部变量即方法中的参数a和b ,该变量和main()方法中的a和b ...

请见我上面的回复,如何确定a和b是形参的?跟数组的操作区别是什么?
作者: 王尧    时间: 2013-12-9 17:00
熊猫86 发表于 2013-12-9 16:28
同上,麻烦请教下怎么确定上个是形参,而数组这个就是实参,谢谢

1.首先你这个创建了一个数组,在栈内存中开辟了main, arr。在堆内存中开辟了数组{1,2},其有个地址值赋给了arr,也就是说arr指向了这个数组。
2.swap在堆内存中把1,2变位,但是地址值没变,SO  arr【0】指向的就是2了。
3.你的第一个问题中main函数的 a ,b。和leftshift中的a,b.是两个完全不同的东东,你把leftshift(int a,int b)换成
leftshift(int haha,int lala)效果是一样的。
4.毕姥爷在视频中也强调过了,你可以再看一遍啦。
5.写程序的时候要向毕姥爷学习,多画图哦~
6.PS 我比较喜欢熊猫85:lol
作者: 赵青超    时间: 2013-12-9 17:08
方法中形参是基本数据类型和是引用数据类型有什么区别捏?
基本数据类型,传递的是变量数据本身,引用数据类型捏,传递的是数据的引用,因为引用数据类型实体在堆内存中,变量引用的是实体的内存地址,形参传递的就是引用,形象的比喻:你在家门前树下埋了一袋钱,你告诉我了埋在哪(引用地址),我去那个树下(引用地址 )把钱拿了。你也没有了。

我看到FFF在二楼卖了个萌,哈哈
作者: 熊猫86    时间: 2013-12-9 17:48
王尧 发表于 2013-12-9 17:00
1.首先你这个创建了一个数组,在栈内存中开辟了main, arr。在堆内存中开辟了数组{1,2},其有个地址值赋给 ...

额,既然讲内存,那就这么问吧,int a=5是在栈中创建一个a,指向常量池中的5,int b=2是在栈中创建一个b,指向常量池中的2,这么说有木有错?那leftshift(a,b)到底在内存中发生了什么呢?如果写int c=leftshift(a,b),这在内存中又发生了什么呢?
作者: 李然    时间: 2013-12-9 17:49
熊猫86 发表于 2013-12-9 16:26
为什么上个函数调用的是两个形参,而下面的数组就可以用函数直接操作呢,为什么数组这个改变的不是形参呢 ...

  兄弟,这个问题应该可以这么理解,虽然说函数swap()接收的 int[] arr也是一个形参,但是这个形参是在栈内存中的一个指向,也可以说是指针,这个指针指向了堆内存中你在主函数中new出的那个数组对象,所以说在这个方法执行时操纵的数据就是你在主函数中定义的那个数组。
   不知道这样说够不够清楚,请见谅,您也可以继续追问。:lol
作者: 熊猫86    时间: 2013-12-9 17:52
赵青超 发表于 2013-12-9 17:08
方法中形参是基本数据类型和是引用数据类型有什么区别捏?
基本数据类型,传递的是变量数据本身,引用数据 ...

请问“基本数据类型,传递的是变量数据本身”这句话该怎么理解?
作者: 熊猫86    时间: 2013-12-9 17:58
李然 发表于 2013-12-9 17:49
兄弟,这个问题应该可以这么理解,虽然说函数swap()接收的 int[] arr也是一个形参,但是这个形参是在 ...

谢谢,其实单纯解释数组这个例子是很明显的,但是基本数据类型的那个leftshift(a,b)到底在内存中发生了什么呢?是激活了一个常量池中的数字7么?
作者: 李然    时间: 2013-12-9 18:08
熊猫86 发表于 2013-12-9 17:58
谢谢,其实单纯解释数组这个例子是很明显的,但是基本数据类型的那个leftshift(a,b)到底在内存中发生了什 ...

个人理解就是在运行leftshift方法时栈内存中又追加了两个int型的变量,方法结束时,改变了新追加的a的值,而你在main的a,b值一直没有发生改变。应该是这样的。
作者: 熊猫86    时间: 2013-12-9 18:21
李然 发表于 2013-12-9 18:08
个人理解就是在运行leftshift方法时栈内存中又追加了两个int型的变量,方法结束时,改变了新追加的a的值 ...

你的意思似乎letfshift(a,b)中的a和b不是main中定义的a和b,那是如何知道传入的两个参数为int型的呢?而且使得int c=letfshift(a,b);的值为7的?
作者: 李然    时间: 2013-12-9 18:36
熊猫86 发表于 2013-12-9 18:21
你的意思似乎letfshift(a,b)中的a和b不是main中定义的a和b,那是如何知道传入的两个参数为int型的呢?而 ...

在函数括号内的参数列表中定义的int。
作者: 熊猫86    时间: 2013-12-9 18:44
李然 发表于 2013-12-9 18:36
在函数括号内的参数列表中定义的int。

不对吧,肯定是在调用函数前先定义好参数类型的,不能说因为调用的函数中参数列表为int型那么传入的肯定是int型,这种逻辑就反了。即不用看调用函数的参数列表就应该提前声明传入的参数类型。
作者: .ˋMr.Ivan    时间: 2013-12-9 19:52
挺有意思的问题,顶一下。
作者: time_out    时间: 2013-12-10 16:27
简单说就是:java中传参都是传递副本的(无论基本类型还是对象)!原本的变量不会被改变。
作者: 李洋-    时间: 2013-12-10 22:42
很好理解,比如a+=b;  是左边数据加上右边数据,然后在把数据赋值给左边
作者: 越,在乎的人    时间: 2013-12-12 22:16
因为main中a,b的值没改变过,如果换成a+=b,那么就是相当于计算之后a的值为7了,所以输出的是7
作者: jing迪    时间: 2013-12-13 00:25
public class Test {
        public static void leftshift(int a, int b) {
                   a+=b;
        }
        public static void main(String args[]) {
                int a = 5, b = 2;
                leftshift(a, b);
                System.out.println(a);
        }
}

a和b在方法leftshift里面是形参  都有就近原则的  方法里面有 不出去找







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