Java方法的参数传递机制实例详解
本文实例讲述了Java方法的参数传递机制。分享给大家供大家参考,具体如下:
参数传递机制
对于程序设计语言来说,一般方法(函数)的参数传递有两种:按值传递和按引用传递。
按值传递意味着当将一个参数传递给一个方法时,方法接收的是原始值的一个副本。因此,如果方法修改了该参数,仅改变副本,而原始值保持不变。按引用传递意味着当将一个参数传递给一个方法时,方法接收的是原始值的内存地址,而不是值的副本。因此,如果方法修改了该参数,调用代码中的原始值也随之改变。
需要注意的是,方法可以修改按引用传递的参数对应的变量值,但不可以修改按值传递的参数对应的变量值,这是两者的最大区别。
Java中的参数传递
Java中的参数传递机制只有一种,就是值传递。在Java中并没有C++的引用传递这种参数传递机制,它所有的参数传递都遵循值传递的机制。
Java中对于对象(数组,类,接口)的传递似乎有点像引用传递,可以改变对象中某个属性的值。但是不要被这个假象所蒙蔽,实际上这个传入方法的值是对象引用的拷贝,即传递的是引用的地址值,所以还是按值传递。
基本类型的参数传递
在方法调用时,传递的参数是按值的拷贝传递;
public class Test { public static void main(String[] args) { Test t = new Test(); int a = 5; t.method(a); // 传递后,method方法对变量值的改变不影响这里的a System.out.println("method调用完后的a: " + a); } private void method(int a){ System.out.println("method中重新赋值之前的a: " + a); a = 10; System.out.println("method中重新赋值之后的a: " + a); } }
执行结果如下:
method中重新赋值之前的a: 5 method中重新赋值之后的a: 10 method调用完后的a: 5
由此可知按值传递重要特点:传递的是值的拷贝,也就是说传递后就互不相关了。下面看一下内存分析:
引用类型的参数传递
在方法调用时,传递的参数按引用进行传递,其实传递的引用的地址,也就是变量所对应的内存空间的地址。
public class Test { public static void main(String[] args) { Person person = new Person(); person.age = 18; // 把main方法中的变量person所引用的内存空间地址,按引用传递给method方法中的person变量 // 请注意:这两个person变量是完全不同的,不要被名称相同所蒙蔽 method(person); System.out.println("调用method方法之后:" + person.age); } public static void method(Person person){ person.age = 20; System.out.println("method方法内第一次修改:" + person.age); person = new Person(); // 新创建一个对象 person.age = 25; System.out.println("method方法内第二次修改:" + person.age); } } class Person { public int age; }
执行结果如下:
method方法内第一次修改:20 method方法内第二次修改:25 调用method方法之后:20
这里传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。
下面我们接着看一个例子:
public class Test { public static void main(String[] args) { int[] a = {5, 10}; method(a); System.out.println("调用完method方法之后:" + a[0]); } public static void method(int[] a){ System.out.println("method内修改a[0]之前:" + a[0]); a[0] = 50; System.out.println("method内修改a[0]之后:" + a[0]); } }
执行结果如下:
method内修改a[0]之前:5 method内修改a[0]之后:50 调用完method方法之后:50
根据结果可知,调用method方法时实际传递的是引用的地址值。
传递String类型的参数
由于String类是final修饰的,不可变,它会在内存中在开辟一块新空间。
public class Test { public static void main(String[] args) { String str1 = new String("test1"); String str2 = "test2"; method(str1, str2); System.out.println("调用method传参str1之后:" + str1 + ", " + str2); } public static void method(String str1, String str2){ System.out.println("method内修改str之前:" + str1 + ", " + str2); str1 = "new1"; str2 = "new2"; System.out.println("method内修改str之后:" + str1 + ", " + str2); } }
执行结果如下:
method内修改str之前:test1, test2 method内修改str之后:new1, new2 调用method传参str1之后:test1, test2
总结:
1)基本数据类型传递的是值的复制,对一个参数的修改不会影响另一个参数;
2)引用类型传引用,形参和实参指向同一个内存地址(同一个对象),所以对参数的修改会影响到实际的对象;
3)String、Integer、Double等immutable的类型特殊处理,可以理解为传值,最后的操作不会修改实参对象(与基本数据类型一致)。
更多java相关内容感兴趣的读者可查看本站专题:《Java面向对象程序设计入门与进阶教程》、《Java数据结构与算法教程》、《Java操作DOM节点技巧总结》、《Java文件与目录操作技巧汇总》和《Java缓存操作技巧汇总》
希望本文所述对大家java程序设计有所帮助。
- 微信小程序能干哪些事,有什么优势?
- 如何告诉手机我是“我”呢?
- 没有任何类型 Windows 的外层实例可访问---Java内部类与外类型
- Hadoop(十二)MapReduce概述
- 安卓第一夜 第一个应用
- spring cloud 学习(1) - 基本的SOA示例
- SVN冲突
- 什么叫微信小程序分销系统?如何通过分销系统来实现你的创业梦
- Hadoop(十一)Hadoop IO之序列化与比较功能实现详解
- 安卓第五夜 维纳斯的诞生
- Eclipse中Project的Deployment Assembly(部署程序集)消失了
- spring-boot 速成(9) druid+mybatis 多数据源及读写分离的处理
- Python标准库14 数据库 (sqlite3)
- spring cloud 学习(4) - hystrix 服务熔断处理
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法