Java 参数传递总结
发布时间:2021-11-20 15:07:32 所属栏目:教程 来源:互联网
导读:网络上有太多关于Java参数传递是传值还是传引用的讨论,其实大多是概念不清,混淆视听。从程序运行的角度来看,参数传递,只有传值,从不传递其它的东西。只不过值的内容有可能是数据,也有可能是一个内存地址。 Java中的数据类型有两大类,即基本类型(primi
网络上有太多关于Java参数传递是传值还是传引用的讨论,其实大多是概念不清,混淆视听。从程序运行的角度来看,参数传递,只有传值,从不传递其它的东西。只不过值的内容有可能是数据,也有可能是一个内存地址。 Java中的数据类型有两大类,即基本类型(primitive types), 共有8种,包括int, short, long, byte, float, double, boolean, char,存在于栈(Stack)中。另一种暂称为对象类型,包括Integer, String, Double等相应基本数据类型的包装类,以及其他所有Java自带和用户自定义的类,这些类数据全部存在于堆中(Heap),如下图所示。 对象类型的数据不同于基本类型的数据,我们所定义的对象变量并不是对象实例本身,而是对象的一个引用(reference)地址,该内存地址用来定位该对象实例在HEAP中的位置。对象实例本身和对象的引用分别保存在HEAP和STACK中,对象引用和对象实例之间的关系好比遥控器和电视机之间的关系,在房间走动的时候里,你只需拿着遥控器就可以控制电视机,而不必带着电视机。而且,即使没有电视机,遥控器也可以独立存在,也就是说你可以定义一个对象类型的变量,但是可以暂时不和一个对象实例关联。多个对象引用也可以指向同一个对象实例。 Heap(堆) Stack(栈) JVM中的功能 内存数据区 内存指令区 存储数据 对象实例 基本数据类型, 指令代码,常量,对象的引用地址 下面我们来看看几个例子,您就会更加明白。 例子1: public class Test { public static void changeValue(int i) { i=2; System.out.println("during test: i = " + i); } public static void main(String[] args) { int i = 1; System.out.println("Before test: i = " + i); changeValue(i); System.out.println("After test: i = " + i); } } 运行结果: Before test: i = 1 during test: i = 2 After test: i = 1 不难看出,虽然在 changeValue(int i)方法中改变了传进来的参数的值,但对这个参数源变量本身并没有影响。其内部原理是,main方法里的变量和changeValue方法的参数是两个不同的变量,以参数形式传递简单类型的变量时,实际上是将参数的值作了一个拷贝传进方法的,那么在方法里再怎么改变其值,其结果都是只改变了拷贝的值,而不是源值。 例子2: public class Test { public static void test(StringBuffer str) { str.append(", World!"); } public static void main(String[] args) { StringBuffer string = new StringBuffer("Hello"); test(string); System.out.println(string); } } 运行结果: Hello, World! 在这个例子里,似乎变量string被“改变”了。但其实改变的并不是string变量本身,也就是说string保存的内存地址并没有被改变,改变的是它所指向的对象实例。内部原理是这样的,在main方法里定义了一个对象引用string,并且把它和一个对象实例关联new StringBuffer。方法调用的时候,string所保存的对象实例的内存地址传递给了test方法的对象引用参数str,这时就有两个对象引用变量指向同一个对象实例。这两个对象引用都可以对该对象实例进行操作,操作结果都有效,因此在test方法执行完之后,对象实例的内容已经被改变了,这个时候再通过main方法里的string引用去查看对象实例的内容,看到的就是改变之后的内容。 例子3: public class Test { public static void test(String str) { str = "World"; } public static void main(String[] args) { String string = "Hello"; test(string); System.out.println(string); } } 运行结果: Hello。 这个结果和上面结果矛盾吗?一点也不矛盾。在这个例子中,参数传递过程和上个例子完全一样,但是在test方法里并不是对原来指向的对象实例进行操作,而是把str指向了另外一个对象实例,当然对原来的对象实例毫无影响。 ![]() (编辑:PHP编程网 - 黄冈站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |