先上一段代码,无码无真相 ^-^
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) 这样的操作符来访问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;
分享到:
相关推荐
Java的引用和函数参数传递Java的引用和函数参数传递Java的引用和函数参数传递Java的引用和函数参数传递
java 中函数的参数传递详细介绍 java 中函数的参数传递详细介绍
C语言 函数调用 参数传递机制 探讨 txt
参数传递是Java语言中函数调用的重要步骤,清楚地了解参数传递的过程是编写出高质量程序所必须的.大多数程序设计语言具有传值调用和传引用调用的两种方法.通过对典型程序的研究与分析可以看出JAVA语言的参数传递总是...
C/C++语言可变参数函数的参数传递机制剖析.pdf
文章对可变参数函数的参数传递机制进行了剖析, 给出了准确、灵活设计可变参数函数的另一种方法
C/C++语言可变参数函数的参数传递机制剖析[归纳].pdf
函数调用参数传递类型(java)的用法介绍..ppt
结合汇编讲解了c语言汇中函数参数是如何传递,如何调用的
函数参数传递
专门讲解函数参数的传递的。希望学学,有很大的帮助
C、C++函数参数传递方式.pdf
C语言函数间参数传递机制的探讨
这是函数参数传递方式,在学c++时可能会需要,希望对大家有所帮助
文档详细描述了C语言函数参数的传递,并举例说明,详细解读
本文主要探讨C/C++语言函数间参数的传值和传地址机制,同时探讨了计算机在调用一个函数时采用什么样的方法来自适应的处理函数中的参数,即函数调用约定.
C/C++函数参数传递机制详解及实例 概要: C/C++的基本参数传递机制有两种:值传递和引用传递,我们分别来看一下这两种的区别。 (1)值传递过程中,需在堆栈中开辟内存空间以存放由主调函数放进来的实参的值,从而...
C++虚函数调用机制初探.pdf
浅析Java引用类型和方法参数传递,浅析Java引用类型和方法参数传递