Java对象中的方法调用机制以及传参陷阱 1 2 3 4 5 6 7 8 9 10 11 public class Test { public static void main (String []args) { Test test=new Test (); int sumNum=test.doubleSum(10 ,20 ); System.out.println("两数之和为" +sumNum); } public int doubleSum (int num1,int num2) { int sum=num1+num2; return sum; } }
执行上述代码得到结果为30.
1 2 3 Test test=new Test (); int sumNum=test.doubleSum(10 ,20 );System.out.println("两数之和为" +sumNum);
这一段代码在main栈里面执行,Test test=new Test();执行之后其内存结构如图,会在堆中创建一个对象。
而当执行int sumNum=test.doubleSum(10,20);时候,栈中会产生一个独立的栈用于运行函数doubleSum。结构如下:
而当在栈中运行到return时,独立的栈运算结束,独立的空间栈被释放,将最终得到的值根据原来保留的地址传回main栈中,并且将值读给sumNum。
方法传参机制常见陷阱 首先说明,Java中分为值传递机制与引用传递机制。
首先我们回顾以下Java中jvm的虚拟内存存储机制,其中包括栈,堆和方法区
栈:一般存放基本数据类型。
堆:用于存放对象。
方法区:常量池(常量,比如字符串等),类加载信息。
而当我们更改时,如果调用的方法仅仅涉及独立方法栈(即运行方法时独立开辟的栈)时,除了return值可以将其结果保存下来之外,其他都不会将更改的结果保存,是因为方法栈在中的方法在运行结束后,就立即释放掉。其保存子啊方法栈中所有的信息都会释放掉,但是如果方法栈云运行的数据信息更改到堆或者方法区时,就可以永久保存。
查看以下的例子:可以发现在运行过程中num1[0]=200; num2[0]=100;这两个语句的运行结果100,200是保存在堆中,即使方法执行完毕释放,也没有影响到堆中的结果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import java.util.Arrays;public class Test { public static void main (String []args) { int []a={10 ,20 }; int []b={30 ,40 }; Test test=new Test (); test.exchangeSum(a,b); System.out.println(Arrays.toString(a)+Arrays.toString(b)); } public void exchangeSum (int [] num1, int []num2) { System.out.println(Arrays.toString(num1)+Arrays.toString(num2)); num1[0 ]=200 ; num2[0 ]=100 ; System.out.println(Arrays.toString(num1)+Arrays.toString(num2)); } }
最后我们来观察以下这个例子:可以发现a数组与b数组的交换只是在栈中的独立方法栈中运行的,exchansum函数结束之后,该栈被立即释放掉。虽然a数组与b数组的地址发生了交换,但是这些改变仅仅在方法栈中运行,并没有传回到堆或者main栈,所以改变并不会被记录。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import java.util.Arrays;public class Test { public static void main (String []args) { int []a={10 ,20 }; int []b={30 ,40 }; Test test=new Test (); test.exchangeSum(a,b); System.out.println(Arrays.toString(a)+Arrays.toString(b)); } public void exchangeSum (int [] num1, int []num2) { System.out.println(Arrays.toString(num1)+Arrays.toString(num2)); int []temp=num1; num1=num2; num2=temp; System.out.println(Arrays.toString(num1)+Arrays.toString(num2)); } }
我们再来运行一段代码,发现函数的作用是将对象置空,这样输出t.name会发生报错,但是结果却是正常的输出,其原因是因为这个过程仅仅在独立方法栈中运行,并没有影响到main中的作用。
1 2 3 4 5 6 7 8 9 10 11 12 13 import java.util.Arrays;public class Test { String name="你好" ; public static void main (String []args) { Test t=new Test (); t.exchangeSum(t); System.out.println(t.name); } public void exchangeSum (Test test) { test=null ; } }