一、前言

  首先先说结论,Java中方法参数传递方式是按值传递。如果参数是基本类型,传递的是基本类型的字面量值的拷贝。如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝。

  接下来深入了解一下为什么是值传递,要想知道Java到底是传值还是传引用,首先要知道基本类型和引用类型的区别。

二、深入了解参数传递

  1.基本类型 和 引用类型的不同之处

基本类型包括8种数据类型:int、short、long、byte、char、float、double、boolean,在方法中定义的非全局基本数据类型变量的具体内容是存储在栈中的;除了基本类型以外的都是引用类型:类、接口类型、数组类型、字符串类型都是引用类型,引用类型变量其具体内容都是存放在堆中的,而栈中存放的是其具体内容所在内存的地址(字符串类型比较特殊,涉及到字符串常量池,这里不做深入研究)。

示例:

int num = 10;      
String str = new String("hello");

注:该图的堆区是经过简化的,实际的情况会复杂点,这里只作示意

如图所示,num是基本类型,值就直接保存在变量中。而str是引用类型,变量中保存的只是实际对象的地址。一般称这种变量为"引用",引用指向实际对象,实际对象在堆中并保存着实际内容。

  2.赋值运算符(=)的作用

num = 20;
str = "world";
注:该图的堆区是经过简化的,实际的情况会复杂点,这里只作示意
 
对于基本类型 num ,赋值运算符会直接改变变量的值,原来的值被覆盖掉。
对于引用类型 str,赋值运算符会改变引用中所保存的地址,原来的地址被覆盖掉。但是原来的对象不会被改变。如上图所示,"world" 字符串对象没有被改变。(没有被任何引用所指向的对象是垃圾,会被垃圾回收器回收)。
  3.值传递和引用传递的区别
值传递是指在调用函数时将实际参数复制一份传递到函数中,引用传递是指在调用函数时将实际参数的地址直接传递到函数中,所以值传递和引用传递的根本区别是是否会复制一份副本。
  4.实例
  例子一(基本数据类型):  
public static void main(String[] args) {
Test test = new Test(); int i = 10;
test.print(10);
System.out.println("main方法输出i:" + i);
} public void print(int j) {
j = 20;
System.out.println("print方法输出j:" + j);
}

  结果:

print方法输出j:20
main方法输出i:10

这个例子应该还是很好理解的,test.print(10)将10作为参数传给print方法, 将10拷贝一份给 j,修改 j 不会影响 i 。

  例子二(引用数据类型):

public static void main(String[] args) {
Test test = new Test();
User user = new User();
user.setName("Tom");
user.setAge("18");
test.print(user);
System.out.println("main方法输出用户:" + user);
} public void print(User user1) {
user1.setName("Mike");
System.out.println("print方法输出用户:" + user1);
}

  结果:

print方法输出用户:User{name="Mike",age="18"}
main方法输出用户:User{name="Mike",age="18"}

  解释: test.print(user)将user对象的引用(即user对象的内存地址)拷贝一份给形参的user1,也就是说main方法中的user引用和print方法的user1引用都指向堆中的同一个user对象,所以user1修改user对象的数据,user的也会相应的改变。

  user1.setName("Mike")执行前

  user1.setName("Mike")执行后

注意:引用数据类型中的字符串类型比较特殊,String被设计成为了不可变类型,为String赋值时不会覆盖以前的对象而是引用一个新的字符串对象(如果新的字符串在常量池中直接返回其引用,否则创建一个字符串对象,详情可以去我的另一篇博客浅析Java常量池 - pluto_blog - 博客园 (cnblogs.com)),在这里我们不考虑新字符串在常量池的情况。

  下面来看各String类型的例子:
public static void main(String[] args) {
Test test = new Test();
String name = new String("Tom");
test.print(name);
System.out.println("main方法输出name:" + name);
} public void print(String name1) {
name1 = "Mike";
System.out.println("print方法输出name1:" + name1);
}

  结果:

print方法输出name1:Mike
main方法输出name:Tom

  解释:由于String被设计成为了不可变类型,为name赋值时不会覆盖以前的对象而是创建一个新的字符串对象并返回引用。

  name1 = "Mike"执行前

  name1 = "Mike"执行后

三、总结

Java中方法参数传递方式是按值传递。如果参数是基本类型,传递的是基本类型的数据拷贝。如果参数是引用类型,因为栈中存的是对象的地址值,所以传递的是该参量所引用的对象在堆中地址值的拷贝,除了特殊的String类型,形参对象可以影响实参对象的值。

Java的参数传递是值传递还是引用传递?的更多相关文章

  1. java中方法的参数传递机制(值传递还是引用传递)

    看到一个java面试题: 问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参 ...

  2. java参数传递时到底是值传递还是引用传递

    java参数传递时到底是值传递还是引用传递(baidu搜集) 问”,很多人的BLOG里都引用这些面试题,最近因为工作内容比较枯燥,也来看看这些试题以调节一下口味,其中有一道题让我很费解. 原题是:当一 ...

  3. java中参数传递--值传递,引用传递

    java中的参数传递——值传递.引用传递   参数是按值而不是按引用传递的说明 Java 应用程序有且仅有的一种参数传递机制,即按值传递. 在 Java 应用程序中永远不会传递对象,而只传递对象引用. ...

  4. Java参数传递是值传递还是引用传递?

    当一个对象被当作参数传递到一个方法后,在此方法内可以改变这个对象的属性,那么这里到底是值传递还是引用传递? 答:是值传递.Java 语言的参数传递只有值传递.当一个实例对象作为参数被传递到方法中时,参 ...

  5. java中值传递和引用传递

    最近工作中使用到了值传递和引用传递,但是有点懵,现在看了下面的文章后清晰多了.一下是文章(网摘) 1:按值传递是什么 指的是在方法调用时,传递的参数是按值的拷贝传递.示例如下: public clas ...

  6. Java中的值传递和引用传递

    这几天一直再纠结这个问题,今天看了这篇文章有点思路了,这跟C++里函数参数为引用.指针还是有很大区别. 当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里 ...

  7. JavaScript 函数参数传递到底是值传递还是引用传递

    tips:这篇文章是听了四脚猫的js课程后查的,深入的理解可以参看两篇博客: JavaScript数据类型--值类型和引用类型 JavaScript数据操作--原始值和引用值的操作本质 在传统的观念里 ...

  8. Does Java pass by reference or pass by value?(Java是值传递还是引用传递) - 总结

    这个话题一直是Java程序员的一个热议话题,争论不断,但是不论是你百度搜也好还是去看官方的文档中所标明的也好,得到的都只有一个结论:Java只有值传递. 在这里就不贴代码细致解释了,让我们来看看一些论 ...

  9. Java是值传递还是引用传递?

    Java的值传递和引用传递在面试中一般都会都被涉及到,今天我们就来聊聊这个问题.这个问题一般是相对函数而言的,也就是Java中所说的方法参数,那么我们先来回顾一下在程序设计语言中有关参数传递给方法的两 ...

随机推荐

  1. jquery 阻止表单提交方法

    <form name="message_form" action="?m=mobilecenter&c=index&a=service" ...

  2. SPRING.NET FRAMEWORK 3.0 GA啦

    THE SPRING.NET FRAMEWORK http://www.springframework.net/ 1. INTRODUCTION Spring.NET contains: A full ...

  3. root密码找回

    1,启动系统时,按上下键,选择第一项,按e. 2,编辑kernel中,将rhgb quiet 替换作init=/bin/sh.回车确认修改 3,根据提示按b键继续启动. 4,进入bash窗口并有管理员 ...

  4. Matlab常用函数:二进制和十进制转换,均值,方差

    文章目录 Size s=size(A) [r,c]=size(A) [r,c,m]=size(A) size(A,n) 二进制和十进制转换 dec2bin mean 均值 mean(a,1) mean ...

  5. Vue学习笔记(二)动态绑定、计算属性和事件监听

    目录 一.为属性绑定变量 1. v-bind的基本使用 2. v-bind动态绑定class(对象语法) 3. v-bind动态绑定class(数组语法) 4. v-bind动态绑定style(对象语 ...

  6. Java基础——逻辑运算符、位运算符

    逻辑运算符.位运算符.三元运算符 逻辑运算符  public class Demon05 {     public static void main(String[] args) {          ...

  7. 37岁Android程序员被裁员,面试大厂被拒,降薪去小公司,心更凉了

    在职场论坛看到这样一个帖子,程序员小A被前公司裁员了,裁员之后也并没有特别气馁,打算重头再来,结果却被现实打击到了. 他大学毕业的时候进入到一家知名互联网公司上班,工作期间,也是不断学习,提升自己的能 ...

  8. 记一次在Windows10桌面环境搭建Jekins的吐血经历

    目录 写在前面 故事背景 踩坑详情 最后总结 写在前面 首先声明,除非万不得已,千万不要在Windows环境做这个事情,否则就等着各种坑吧. 本人一贯的立场都是坚持用正确的方法做事,显然在Window ...

  9. Java自定义注解使用和详解

    前言 我们在做开发springboot 项目时候会遇到各种各样注解,使用各种各样注解,极大的简便了我们开发流程,方式,从JDK5开始支持 注解是Java语言的一种强大的功能 可以理解为代码上的特殊标记 ...

  10. 清理docker常用命令

    0.查看docker占用空间docker system df1.一键删除所有已经停止的容器 docker container prune 2.删除所有容器(包含停止的 正在运行的) docker rm ...