可能很多人都知道参数有形参和实参之分,却不知道区别到底是什么;知道Java中内存分为栈、堆、方法区等5片内存,不知道每片内存中保存的都是什么;关于参数的传递到底是值传递还是引用传递傻傻分不清楚。本文将为你逐一揭秘!

一、形参和实参

  • 形参就是定义方法时,该方法携带的参数。比如定义如下方法
public static void test(String name){System.out.println(name);
}

test方法中的参数name就是形参,只有在test方法在被调用这个name的生命周期才开始,才会分配内存空间,当test方法调用完后,这个name也就不复存在。

  • 实参方法在被调用时实际传入的参数值,实参在方法调用前就已经被初始化。看例子
public static void main(String[] args){String name = "刘亦菲";test(name);
}

这个String name = "刘亦菲"中这个name,在test方法被调用之前就就已被创建并且初始化,在调用test方法时,它就被当作实际参数传入,这就是实参。

二、Java中的内存

Java中内存分为5片,分别是栈、堆、方法区、程序计数器、本地方法栈
1、栈
又称虚拟机栈。特点是先进后出。栈的线程是私有的,也就是线程之间的栈是隔离的。栈中有若干栈帧,每个栈帧对应一个方法。也就是说,当程序开始执行一个方法时,就会在栈中创建一个栈帧入栈,方法结束后,该栈帧出栈。看下面的图解

每个栈帧主要包括

  • 局部变量表存储方法中的局部变量。当局部变量是基本类型时,存储的是变量的值;当变量是引用类型时,存储的是地址值。
  • 运行时常量池的引用存储程序执行时可能会用到的常量的引用。
  • 方法返回地址存储方法执行完成后的返回地址。

2、堆
堆内存用来存储对象和数组。数组以及所有new出来的对象都存储在堆内存中。在JVM中只有一个堆,所以堆是被所有线程共享的。

3、方法区
方法区也是所有线程共享的区域,主要存储静态变量、常量池等。

三、数据在内存中的存储

1、基本类型的存储

  • 基本类型的局部变量变量以及数值都是存储在栈内存中。比如在某个方法中定义有如下局部变量
int age = 6;
int grade = 6;
int weight = 50;

先创建一个age变量,存储在栈帧中的局部变量表,然后查找栈中是否有字面量值为6的内容,如果有,直接把age指向这个地址,没有开辟内存空间来存储"6"这个内容,同时让age指向它。当创建grade变量时,因为已经有字面量为"6"的内容了,所以直接拿过来用。所以栈中的数据在当前线程下是共享的。上面的代码在内存中的图解如下

如果给age重新赋值

age = 10;

难么就会在栈中查找是否有字面量为"10"的内容,有就直接拿来用,没有就开辟内存空间存储"10",然后age指向这个10。所以基本类型的变量,变量值本身是不会改变的,重新赋值后,只是指向了新的引用而已。

  • 基本类型的成员变量基本类型的成员变量的变量名和值都是存储在堆内存中的,其生命周期和对象是一致的。看下面的代码
public class User{private int age;private String name;private int grade;......
}

调用

User user = new User();

在内存中的存储图解

  • 基本类型的静态变量基本类型的静态变量存储于方法区的常量池中,随着类的加载而加载。

2、引用类型的存储
通过上图可以发现,执行

User user = new User();

时分两个过程

User user;// 定义变量
user = new User();// 赋值

定义变量时,会在栈中开辟内存空间存放user变量;赋值时会在堆内存中开辟内存空间存储User实例,这个实例会有一个地址值,同时把这地址值赋给栈中的user变量。所以引用类型的变量名存储在栈中,变量值存储的是堆中相对应的地址值,并不是存储的实际内容。

四、参数传递问题

关于参数的传递,可能有点难理解,到底是值传递还是引用传递?下面一起来学习一下

  • 值传递方法调用时,实际参数把它的值的副本传递给对应的形式参数,此时形参接收到的其实只是实参值的一个拷贝,所以在方法内对形参做任何操作都不会影响实参。看下面一段代码
public class Test {public static void test(int age,String name){System.out.println("传入的name"+name);System.out.println("传入的age:"+age);age = 66;name = "张馨予";System.out.println("方法内重新赋值的name"+name);System.out.println("方法内重新赋值的age:"+age);}public static void main(String[] args){String name = "刘亦菲";int age = 44;test(age,name);//调用方法System.out.println("方法执行后的name:"+name);System.out.println("方法执行后的age:"+age);}
}

执行结果如下

从结果可以发现,name和age在方法调用后并没有改变,所以传入方法的只是实参的拷贝。

  • 引用传递当参数是对象的时候,其实传递的对象的地址值,所以实参的地址值传给形参后,在方法内对形参进行操作会直接影响真实内容。看下面的代码
    定义对象
@Data
public class User {private String name;private int age;
}

测试

public class Test {public static void userTest(User user){System.out.println("传入的user:"+user);user.setName("张馨予");user.setAge(20);System.out.println("方法内重新赋值的user:"+user);}public static void main(String[] args){User user = new User();user.setName("刘亦菲");user.setAge(18);userTest(user);//调用方法System.out.println("方法执行后的user:"+user);}
}

结果如下

可以看到在方法内对user重新赋值,直接影响这个对象,所以方法执行完毕后输出的是修改后的user。

对上面的测试方法稍作修改

public class Test {public static void userTest(User user){System.out.println("传入的user:"+user);user = new User();//新增这行代码user.setName("张馨予");user.setAge(20);System.out.println("方法内重新赋值的user:"+user);}public static void main(String[] args){User user = new User();user.setName("刘亦菲");user.setAge(18);userTest(user);//调用方法System.out.println("方法执行后的user:"+user);}
}

执行结果如下

结果却是,方法执行后的user竟然没改变。

分析一下这两次的执行过程
第一次

第一次执行过程如上图,main方法进栈后,在堆中new了一个user对象x0001,然后调用userTest方法,userTest方法进栈,并且把user对象的地址值x0001传入userTest方法,所以在userTest方法中对user进行操作直接影响地址值为x0001的对象。所以就出现了第一次运行结果。

第二次

第二次执行过程如上图,main方法进栈后,在堆中new了一个user对象x0001,然后调用userTest方法,userTest方法进栈,并且把user对象的地址值x0001传入userTest方法,在此之前都是和第一次一样的。接下来在该方法中有

user = new User();

到了这里,又在堆中new了一个user对象x0002,然后让栈中user变量指向新的user对象的地址值x0002。所以接下来在方法中对user的操作都是对地址值为x0002的对象的操作,自然不会影响到地址值为x0001的对象。所以就出现了第二次的运行结果。

  • 小结由上面的案例可以得出结论,基本类型传的是值的副本,引用类型传的是地址值,所以不论传的是引用类型还是基本类型,其实都是值传递。

java到底是引用传递还是值传递?相关推荐

  1. java int 传引用吗_Java值传递还是引用传递?

    从我实习面试开始就有在面试中遇到过这个问题:Java是值传递还是引用传递? 当时的我只会背背面试题,但是网上的答案有些还是错的,导致我决心写这一篇文章. 虽然网上已经有很多文章珠玉在前,但是我还是想写 ...

  2. java包装和引用_回顾值传递和引用传递关于Java是值传递还是引用传递,网上有不一样的说法。1、基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递。2...

    回顾值传递和引用传递 关于Java是值传递还是引用传递,网上有不一样的说法. 1.基本类型或基本类型的包装类以及String是值传递,引用类型是引用传递. 2.Java中只有值传递. 关于这个问题应该 ...

  3. java还值_Java到底是引用传递还是值传递

    前言 前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢? public void test(){ String str = "hello"; change(str); S ...

  4. Java到底是引用传递还是值传递

    前言 前段时间在群里看到类似这样一个问题,下面的代码会输出什么呢? public void test() {String str = "hello";change(str);Sys ...

  5. java中是引用传递还是值传递....

    刚才与Z师兄聊天,他提问: 你说java中是引用传递还是值传递啊? 当时俺搞混了这个"传递"的意思, 本来以为是对象的实例化比如: abc a=new abc(); 这个a 是引用 ...

  6. java引用传递_理解Java中的引用传递和值传递

    关于Java传参时是引用传递还是值传递,是一个讨论比较多的话题, 有说Java中只有值传递,也有些地方说引用传递和值传递都存在,本篇记录思考过程,不保证正确性, 感兴趣的同学一起讨论. 1.基本类型和 ...

  7. java中的参数传递(只有值传递没有引用传递)

    Java中只有传值调用(值传递),没有传址调用(址传递或者引用传递).所以在java方法中改变参数的值是不会改变原变量的值的,但为什么改变引用变量的属性值却可以呢?请看下面的解答. java中的数据类 ...

  8. java是引用传递还是值传递_流言终结者:Java是引用传递还是值传递?

    前言 今天聊一个很小的话题,引用传递和值传递.为什么拉出这个话题呢?因为自己太菜吧-在这上边栽了跟头.所以今天就聊一聊Java中是引用传递还是值传递. 正文 小A:MDove,我有一个疑问:Java的 ...

  9. Java修炼之路——基础篇——值传递

    什么是值传递?引用传递? 值传递:值传递是将变量的一个副本传递到方法中,方法中如何操作该副本,都不会影响原变量的值.引用传递:引用传递是将变量的地址传递到方法中,方法中操作该变量,会对其产生影响. 为 ...

  10. Java基础篇:什么是值传递

    Java类的结构的内存解析 内存分为4部分:栈.堆.方法区.静态域 栈:对象的引用名,数组的引用名,局部变量(方法的形参,方法内定义的变量,代码块中定义的变量) 堆:new 出来的"东西&q ...

最新文章

  1. 以太坊白皮书_区块链60讲第33集~什么是以太坊?
  2. ps查看oracle进程数,通过ps -ef | grep oracle查出的进程,怎样对应数据库中跑的进程...
  3. pyecharts应用2 柱状图
  4. MYSQL交通系统查询,城市公交查询系统的设计与实现(SSH,MySQL)(含录像)
  5. Boost:bind绑定的function<>测试程序
  6. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1092:求出e的值
  7. MicroProfile 2.2 BOM导入支持
  8. 如何愉快地学习 Go 语言?来场 Go 之旅吧!
  9. Breeze:抢先体验Kubernetes 1.13.0高可用图形化部署
  10. 理解分布式和集群的区别
  11. XP系统下IE7访问HTTPS网站提示“此网站的安全证书有问题”的解题思路
  12. ADT(Android) — Eclipse开发连接夜神模拟器方法(亲测有效!)
  13. 机器学习项目实战合集列表
  14. 反欺诈概念库-物联卡/物联网卡/流量卡
  15. 阿里巴巴常用的 12 个后端开发工具,建议你快快收藏!
  16. matlab结构力学仿真,MATLAB在结构力学分析中应用.doc
  17. java espresso车架,只爱钢架公路:Casati Espresso
  18. jsp+ssm计算机毕业设计逸尘房屋销售管理系统【附源码】
  19. gunicorn工作原理
  20. [MySQL] 统计图数据查询 (MySQL查询时间范围内所有日期)

热门文章

  1. AutoIt vs QTP
  2. 24 - 面向对象1
  3. 75%半导体产能集中在亚洲,让美国半导体霸主地位岌岌可危
  4. 百度搜索引擎排名规则,最新排名与优化的因素有哪些?
  5. 辞职信微信html,女教师辞职信走红微信背后:“走心”
  6. mysql 8.0 配置文件my.cnf中文注解
  7. 视频教程-大数据与数据仓库入门到精通-Hadoop
  8. vlookup和sumif函数使用通配符
  9. MySQL Error 1114
  10. 携程工作感言(一)(6.30)