一、前言

  首先先说结论,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. Java集合框架全解

    Collection 集合 集合接口有2个基本方法: public interface Collection<E> { //向集合中添加元素.如果添加元素确实改变了集合就返回 true, ...

  2. Spring Security OAuth2 远程命令执行漏洞(CVE-2016-4977)

    影响版本: 2.0.0-2.0.9 1.0.0-1.0.5 poc地址 https://github.com/vulhub/vulhub/blob/master/spring/CVE-2016-497 ...

  3. CSS实现隐藏滚动条并可以滚动内容

    方法一: 计算滚动条宽度并隐藏起来,其实我只是把滚动条通过定位把它隐藏了起来,下面给一个简化版的代码: <div class="outer-container"> &l ...

  4. Java ParallelStream

    ParallelStream 处理数据 Stream 接口提供了parallelStream方法来将集合转换为并行流.即将一个集合分为多个数据块,并用不同的线程分别处理每个数据块的流. 并且使用par ...

  5. Esxi安装Kali2并开启远程桌面

    Kali安装 登录Vmware Esxi页面,选择"创建/注册虚拟机",步骤和创建其它Linux主机类似(Esxi的安装和介绍可以参考上一篇文章) 不同的地方是,客户机操作系统版本 ...

  6. 『Java』StringBuilder类使用方法

    String类存在的问题 String类的底层是一个被final修饰的byte[],不能改变. 为了解决以上问题,可以使用java.lang.StringBuilder类. StringBuilder ...

  7. javaScript学习DOM模型

    DOM 全称是 Document Object Model 文档对象模型大白话,就是把文档中的标签,属性,文本,转换成为对象来管理                                   ...

  8. Spring Cloud Alibaba - Spring Cloud Stream 整合 RocketMQ

    Spring Cloud Stream 简介 在微服务的开发过程中,可能会经常用到消息中间件,通过消息中间件在服务与服务之间传递消息,不管你使用的是哪款消息中间件,比如RabbitMQ.Kafka和R ...

  9. MySQL学习03(MySQL数据管理)

    MySQL数据管理 外键 外键概念 如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键.由此可见,外键表示了两个关系之间的相关联系.以另一个关系的外键作主关键字的表被称为主 ...

  10. Java工具类-输入输出流

    输入输出流 1.概念 输入输出流:文件复制,上传 输出流: System.out.println() 写操作,程序将字符流写入到"目的地",比如打印机和文件等 输入流 :Scann ...