一、前言

  首先先说结论,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. 论文笔记:(2021CVPR)PAConv: Position Adaptive Convolution with Dynamic Kernel Assembling on Point Clouds

    目录 摘要 1.引言 2.相关工作 将点云映射到常规二维或三维栅格(体素) 基于MLPs的点表示学习 基于点卷积的点表示学习 动态卷积和条件卷积 3.方法 3.1 回顾 3.2 动态内核组装 Weig ...

  2. 基于CAS实现SSO单点登录

    1. 概述 1.1. 什么是SSO? 单点登录( Single Sign-On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要 登录一 ...

  3. 2010 NOIP提高组题解

    机器翻译 用队列模拟题意即可 #include<cstdio> #include<iostream> #include<cstring> using namespa ...

  4. Java面向对象03——类与对象的创建

    类的创建与初始化对象 age: 以类的方式组织代码,以对象的组织(封装)数据  package oop.demon01.demon02; ​ // 学生类(抽象模板) public class Stu ...

  5. 我快被Framework源码烦死了!

    前言 这段时间,忙到没时间学新东西,都有点心有余而力不足,想着抽空补补课,于是重读了Framework源码. 因为Framework源码太重要了,像掉帧监控.函数插装.慢函数检测.ANR 监控.启动监 ...

  6. linux c语言学习笔记之守护进程

    哈尔滨理工大学软件工程专业08-7李万鹏原创作品,转载请标明出处 http://blog.csdn.net/woshixingaaa/archive/2010/06/06/5651095.aspx 守 ...

  7. 从跨域与同源策略谈CSRF防御与绕过

    之前偶然看到群里有小伙汁问这个token相关的问题,当时我酝酿了一下子,没想好怎么总结,今天来说一下 CSRF在过去还属于OWASP TOP10 ,现在已经不是了(补充一点:关于OWASP API 请 ...

  8. MATLAB—命令窗、文件夹、路径、工作内存区、帮助系统

    文章目录 一.命令窗操作 1.命令窗的显示 2.数据显示格式 3.命令行的标点符号 4.命令窗常用控制命令 5.指令行编辑 二.当前文件夹和路径设置 1.当前文件夹及其使用 2.搜索路径和路径设置 三 ...

  9. 《JERRY Hexo & GitHub 静态网站搭建说明》

    JERRY-Hexo-GitHub <JERRY Hexo & GitHub 静态网站搭建说明> 原创内容,转载请注明出处! 一.前言 1.1 什么是 Hexo? 一个基于 Nod ...

  10. .Net 之进制转换 余位补全

    十进制转二进制 Convert.ToString(n, 2) 其中 n -- 源类型 可以是shrot Byte Int Uint Long 2 -- 目标位 可以是2,8,10,16 同理十进制转1 ...