Java语言中函数参数的传递机制初探_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > Java语言中函数参数的传递机制初探

Java语言中函数参数的传递机制初探

 2014/12/3 16:11:34  focus2008  程序员俱乐部  我要评论(0)
  • 摘要:先上一段代码,无码无真相^-^importjava.util.ArrayList;importjava.util.Date;publicclassJavaReference{publicstaticvoidchange(Datedate){date=null;}publicstaticvoidchangeList(ArrayList<Integer>lst){lst.add(3);lst=null;}publicstaticvoidmain(String[]args)
  • 标签:函数 Java
先上一段代码,无码无真相 ^-^

class="java">
import java.util.ArrayList;
import java.util.Date;

public class JavaReference
{
	public static void change(Date date)
	{
		date = null;
	}
	
	public static void changeList(ArrayList<Integer> lst)
	{
		lst.add(3);
		lst = null;
	}
	
	public static void main(String[] args)
	{
		Date d = new Date();		
		System.out.println(d);		
		JavaReference.change(d);		
		System.out.println(d);	// 这里会打印  null 吗?
		
		ArrayList<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		System.out.println(list.size());
		
		JavaReference.changeList(list);		
		System.out.println(list.size());	// 这里会报空指针错误码?还是会打印 3 呢?
	}
}

上面的 d 会打印null吗?
最后的打印语句会报空指针吗?

继续看之前,请您在心中该处答案,并且分析为什么结果是这样的。

===================================华丽的分割线======================================

打印结果为:
Wed Dec 03 13:35:21 CST 2014
Wed Dec 03 13:35:21 CST 2014
2
3

您答对了吗?

为什么结果是这样的呢?
原因分析:
    有人说Java中没有指针,但是java中有处处是指针。指针的本质是什么呢?学过C/C++的应该不陌生,指针是一个变量,他自己的内存空间在栈上分配,既然指针是一个变量,那么这个变量的值是什么呢?指针这个变量专门用于保存 地址值 ,而这个地址值,在Java中是一个堆上的对象的地址。在C/C++中指针也会指向栈上的变量或者对象。但是在Java中指针或者说引用只能指向堆上的某个对象。

在Java中函数参数的传递,是值传递呢?还是引用传递呢?

没有异议:绝对是值传递!

有了上面的基础,再来分析上面的结果:
JavaReference.change(d);
change函数将 d 这个保存了 new Date() 语句所产生的对象的地址传给了函数change,在C/C++中,如果要在change函数中修改 d 所指向的对象,必须如下操作:
*d = null;

这里的含义是: *d  表示取得 d 所指向的对象,就是得到d所指向的对象,然后再来修改d所指向的那个对象。

但是在java中不能这样操作,那么java中change函数中的
date = null

是什么意思呢?
是这样的:change(d) 将 new Date() 对象的地址传递给了 change函数的参数 date, 此时date是change函数局部变量,然后再将null赋值给这个局部变量,那么实际参数 d 的值变了吗?没有!d 还是指向 new Date() 所产生的那个对象。
所以 System.out.println(d); 不会打印null,他会自动调用 d.toString()

注意注意:d.toString() 这个调用很神奇!!!! 他为什么神奇,他哪里神奇呢?
我们知道 d 保存了指向 new Date() 的那个对象,那么 d 是如何访问 new Date() 对象的方法的呢?语法我们都知道: d.toString(),但是其中的暗含了下面的过程:
1)先获得 d 指向或者说引用的对象,即那个 new Date() 产生的对象;
2)然后调用他的 toString()方法; 

在C/C++中相当于: d->toString(); 或者: (*d).toString();
看到这里,您应该明白了,因为java中没有 (*d) 这样的caozuofu.html" target="_blank">操作符来访问d所指向的对象,所以java中直接省略了(*d) 或者,将 (*d) 暗含在 d.toString()中了。

所以java 中的 d.toString() 等价于C/C++中的 (*d).toString().

明白了这一点就一切真相大白了。

JavaReference.changeList(list);

调用,在changeList中,将list所指向的 new ArrayList<Integer>() 对象的地址传递给了changeList的局部变量lst ,然后 lst.add(3) 相当于C/C++中的 (*lst).add(3);即先获得lst这个局部变量中保存的地址所指向的对象,也就是指向 new ArrayList<Integer>() ,然后调用这个对象 的 add(3)方法。所以list.size() == 3

那么 局部变量 lst = nul; 是什么意思呢?他只是将 局部变量 lst 的值赋值为null,他没有改变实际参数 list.

lst = null 不等价于C/C++中的 (*lst) = null;

原因是这里没有使用调用操作符 “.”,他就是普通的局部变量的赋值操作。

调用操作符 “.”为什么会相当于C/C++中的 (*lst).add(3)呢?即局部变量 lst 调用函数 add(3) 时,为什么先要 访问 lst 所指向的对象 new ArrayList<Integer>() ??

废话,不先访问他指向的对象,怎么去调用他的方法呢???

所以到这里:最重要的是,java中对象参数的传递时基于值的传递,传递的是实际参数所引用的那个对象的地址。指针,或者说引用在调用函数时,会自动先去访问它的地址所指向的那个对象,也就是它说引用的那个对象,然后调用该对象的方法。所以就修改了该对象。所以最后的list.size() == 3;





发表评论
用户名: 匿名