黑马程序员技术交流社区

标题: 为什么int型变量的值没有被更改?? [打印本页]

作者: 汪璨    时间: 2012-6-26 13:41
标题: 为什么int型变量的值没有被更改??
public class Test {
        public static void main(String[] args){
                int[] array = new int[1];
                int i = 0;
                method_1(array,i);
                System.out.println(array[0]+" "+i);
        }
        public static void method_1(int[] array,int i){
                array[0] = 1;
                i = 1;
        }
}这个程序中,有一个数组和一个int型变量,用method_1()方法分别改变数组和 i 的值,为什么最后数组被更改了, i 的值却没有更改依然是0,基础不好,求解
作者: 李天甲    时间: 2012-6-26 13:55
public class Test {
       public static void main(String[] args){
               int[] array = new int[1];  //生成一个int 类型的数组对象
               int i = 0;  //生成一个int的基本变量
               method_1(array,i);  //传递进去的int[] array是一个引用,指向的地址就是上面生成的new int[1]开辟的空间,而传递进去的i仅仅是个基本变量的值
               System.out.println(array[0]+" "+  i);  
       }
        public static void method_1(int[] array,int i){   
               array[0] = 1;
               i = 1;
       }
}
参见上面标示,不同的颜色标示了不同的值..
作者: 李文龙    时间: 2012-6-26 14:12
楼主,你这是没有了解局部变量的意思,局部变量的值在函数体里面才会有效,出了函数,这个值的内存空间就会被释放,
public static void method_1(int[] array,int i){   
               array[0] = 1;
               i = 1;
}
这个函数体里面,i 的值是1,只存在于这个函数里面,如果你有返回或者是在函数体里面直接打印,那么 i 的值就是1,而你的代码
  int i = 0;  
  method_1(array,i);
这只是调用了这个函数,将实参  i  的值传递给了形参,本质上没有发生根本的改变,所以下边打印的 System.out.println(array[0]+" "+  i);  i 的值还是0,如果你想验证,可以这样
public static void method_1(int[] array,int i){   
               array[0] = 1;
               i = 1;
               System.out.println(array[0]+" "+  i);  
}
至于为什么数组的值被改变了,这是因为传递的参数是数组的引用,等同于就是这个数组,当然会发生改变了,而 i  只相当于是 实参传递值给形参,不会对 实参值造成任何的改变
作者: 贾飞雨    时间: 2012-6-26 14:13
这两个数据的存储类型是不同的,其中其中数组是在堆内存中,当你在方法区给 array[0] = 1;赋值的时候,这个是指向对内存中的数组的一号元素的,也就是说,你给他赋值,对内存中的数组array[0]的值更改为1,所以当你的时候是打印的同一个数组,而int i和你在方法区的int i却并不是一个数,在方法区的int i是局部变量,用完即释放,所以你打印出来的还是原来那个数,
这里有个结论,以后记住就ok了,局部变量用完即释放,无论你在用什么方法对它操作,之后它还是那个数,数组却是同一,改了就真改了
作者: 周朋飞    时间: 2012-6-26 14:44
java当中除了基本数据类型,都是引用类型。 数组也是一个对象也是一个引用类型。
通过new来给你定义的数组在堆中分配了空间,然后将这个空间的引用赋给你定义的数组变量array  你的这个变量array是存放在栈内存当中的指向的是对内存当中的对象
然后你把array作为参数传进去之后,实际上传的是堆内存对象的引用,array【i】其实就是对里面的对象的值,你进行改变之后,那么原来的引用并没有变,但是指向的内容却改变了

你的方法并没有返回值,只是在方法里面对i进行改变,但是在主程序里i的值还是没有改变,这就是变量作用域的问题。
作者: 周朋飞    时间: 2012-6-26 14:44
java当中除了基本数据类型,都是引用类型。 数组也是一个对象也是一个引用类型。
通过new来给你定义的数组在堆中分配了空间,然后将这个空间的引用赋给你定义的数组变量array  你的这个变量array是存放在栈内存当中的指向的是对内存当中的对象
然后你把array作为参数传进去之后,实际上传的是堆内存对象的引用,array【i】其实就是对里面的对象的值,你进行改变之后,那么原来的引用并没有变,但是指向的内容却改变了

你的方法并没有返回值,只是在方法里面对i进行改变,但是在主程序里i的值还是没有改变,这就是变量作用域的问题。
作者: 孙飞    时间: 2012-6-26 15:10
你虽然调用了method_1函数,在函数中你给i赋值1,但是你只是赋进去了值,i是局部变量在栈中开辟内存,当局部变量一但脱离这个作用域,内存立即释放,它只在method_1里才有效,而你并没有把它输出,所以当出了函数就会被释放,所以你输出语句中的i和你method_1函数里的i都没有关系,输出语句只在所在函数里找到i,就是你赋0值的i。数组是在堆内存中开辟空间来存储的,而你传进去的是一个数组的引用,并且把值赋给了数组中0角标位,堆中的对象只有再没有引用变量指向的时候才会成为垃圾,但仍占有内存,在以后的不确定时间内才会被释放,所以你输出的是数组中0角标位上的值
作者: 黑马_张伟    时间: 2012-6-26 15:46
public class Test {
        public static void main(String[] args){
                int[] array = new int[1];
                int i = 0;
                method_1(array,i);
                System.out.println(array[0]+" "+i);
        }
        public static void method_1(int[] array,int x){
                array[0] = 1;
                x = 1;
        }
}

将你的程序改成这样。你就懂了。
作者: 谭立文    时间: 2012-6-26 15:52
首先要弄清楚java中实参与形参的区别.
1、形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。

2、在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。而在引用调用的机制当中是将实参引用的地址传递给了形参,所以任何发生在形参上的改变实际上也发生在实参变量上。
作者: 赵庆礼    时间: 2012-6-26 18:38
public class Test {
        public static void main(String[] args){
                int[] array = new int[1];
                int i = 0;
                method_1(array,i);//传进去的i是一个形参,是一个变量值,函数结束以后,i的值就不存在,而传的array是数组的首地址,函数调用结束后,数组值将会改变
                System.out.println(array[0]+" "+i);//打印的还是main函数中的i,其值不变。
        }
        public static void method_1(int[] array,int i){
                array[0] = 1;
                i = 1;
        }
}
作者: 陈淑飞    时间: 2012-6-26 19:04
谭立文 发表于 2012-6-26 15:52
首先要弄清楚java中实参与形参的区别.
1、形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放 ...

纠正一下各位的说法。 什么叫形参,什么叫实参。
不管哪个语言中c 也还 脚本js 或T-sql等也好,都有函数,而且都支持带参数的函数。

只不过,在Java中 函数 叫方法。但大家在学java时,还是保留了以前的形参与实参的叫法。

比如
function  ... doSome(int a) {
  // 函数体   ----这里的a 叫做形参 就是形式参数
}

而在函数体 调用时  比如

... main(String[] args){
   doSome(8);
   int c = 88;
   doSome(c);  //这里的c与8 都叫实际参数  即实参
}

简单来讲
1. 形参 是被人家传入的值, 等待人家给一个值给它。
2. 实参 是主动传个值给形参。


另外在 java中,与C的区别是,没有指定引用传递,对于数组与对象,是传将此数组的首位元素的内存地址 与 对象在内存的地址  复制 一份 传给个形参。
所以你在操作 数组与对象 时, 改变它的元素值或属性时。 被调用处引用的数组或对象也就变了。

而 基本数据类型  如 字符型 char 整数类型 byty 、short、int、long  数值类型 float 、double 布尔型 boolean  变量 在 各自方法体中,有自己的独立内存地址。 所以你复制 一个值 或 叫实参int 传个 值给形参, 最终是影响不了实参的值的。 这两个有独自的内存地址,各玩各的呢。出个函数体,这些形参 变量都挂了呢。

所以你想对 函数/方法 处理的基本数据类型的结果 ,想传回去的话,得定义函数的返回类型了。....







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