java中date类型如何赋值_Java 中的类型传递问题解惑
来源:
https://blog.biezhi.me/2018/11/java-pass-by-value.html
我之前一直犯了一个错误,认为 Java 中是有引用传递的,其实不然,写这篇文章一方面是纠正自己的理解,另一个是希望看到文章的人不要犯同样的错。
类型传递有什么蹊跷?
要讨论 Java 中是值传递还是引用传递,先来看看如何定义值传递和引用传递。
值传递(pass by value):在调用函数时将实际参数拷贝一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递(pass by reference):在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
它们都是在发生函数调用时的一种参数求值策略,这是对调用函数时,求值和传值的方式的描述,而非传递的内容类型(内容指:是值类型还是引用类型,是值还是指针)。值类型/引用类型,是用于区分两种内存分配方式,值类型在栈上分配,引用类型在堆上分配。一个描述内存分配方式,一个描述参数求值策略,两者之间无任何依赖或约束关系。下面通过一些代码来理解这些话。
Java 代码的味道
在 Java 中有基本类型如 int
、boolean
、char
,也有对象类型如 Object
、HashMap
、Integer
等。
最简单的例子
1public static void swap(int a, int b) { 2 int x = a; 3 a = b; 4 b = x; 5 System.out.println("swap a: " + a); 6 System.out.println("swap b: " + b); 7} 8 9public static void main(String[] args) {10 int a = 3;11 int b = 4;12 swap(a, b);13 System.out.println("a = " + a);14 System.out.println("b = " + b);15}
对于这段代码的输出是:
1swap a: 42swap b: 33a = 34b = 4
int
是一个基本类型,我们将 2 个变量的值传入到 swap
方法中,它们实际的结构是这样的:
引用类型的例子
1static class Foo { 2 String name; 3 4 public Foo(String name) { 5 this.name = name; 6 } 7} 8 9static void change(Foo myfoo) {10 System.out.println("change input myfoo.name: " + myfoo.name);1112 myfoo.name = "FiFi";13 System.out.println("change new myfoo.name: " + myfoo.name);14}1516public static void main(String[] args) {17 Foo foo = new Foo("Jerry");18 change(foo);1920 System.out.println(foo.name);21}
对于这样一段代码的输出是:
1change input myfoo.name: Jerry2change new myfoo.name: FiFi3FiFi
对于 change
方法接收到的 name
是 Jerry 我们可以理解,修改后方法内输出的 FiFi 也可以理解,因为在同一函数体内,变量的修改必然是可见的。需要解释的就是外部的修改也会发生变化,这是为啥呢?
看了这幅图你大概就明白了,我们 new Foo("Jerry")
这句话会在堆上开辟一块内存空间,假设叫它 0xabcd
好了,把这块内存赋值给一个名为 foo
的引用类型。进入 change
方法的时候就会传递一份 foo
引用类型的拷贝(参数入栈),我故意把这个变量名写为 myfoo
防止大家理解错误,myfoo
和 foo
这 2 个引用类型都指向同一块堆内存空间,在 change
方法内通过 myfoo
修改的值也会影响到其他指向这块内存的引用类型。
结论:对于引用类型,是通过传值的方式传引用(引用类型)。这句话可能会有点儿绕,不要死记硬背它。
上面的例子都是演示了 Java 中的值传递,假设 Java 里有引用传递会是什么样子呢?来看看这段代码
1static void change(Foo myfoo) { 2 System.out.println("change input myfoo.name: " + myfoo.name); 3 4 // 改变 foo 的指向,让它指向一个新的内存 5 myfoo = new Foo("biezhi"); 6 System.out.println("change new myfoo.name: " + myfoo.name); 7} 8 9public static void main(String[] args) {10 Foo foo = new Foo("Jerry");11 change(foo);1213 System.out.println(foo.name);14}
这段代码的输出是
1change input myfoo.name: Jerry2change new myfoo.name: biezhi3Jerry
可能你看到这里已经恍然大悟了,如果 Java 中可以传递引用意味着 myfoo = new Foo("biezhi");
这行代码的修改会影响到之前的 foo
变量,会让 foo
和 myfoo
指向同一块新的地址,然后导致外部的 foo.name
会输出 biezhi。
我们看到结果不是这样的,正因为是传值(拷贝了一份)。这行代码会创建一个新对象,让 myfoo
指向新内存,而 foo
指向的还是旧的内存,所以 myfoo
的是不会影响到外部的。
biezhi 的新疑问
看到上面其实值传递的概念和理解已经比较清晰了,之前又遇到一个问题,来看看代码吧
1static void change(Integer num) { 2 System.out.println("change input num: " + num); 3 num = 2333; 4 System.out.println("change new num: " + num); 5} 6 7public static void main(String[] args) { 8 Integer num = 1; 910 change(num);11 System.out.println(num);12}
我当时的疑问,Integer
是引用类型吗?传递给 change
方法的参数修改后会影响外部吗?
Integer
创建出来的是一个对象(自动装箱),所以是引用类型不会影响到外部
第二个问题为什么就不会影响到外部呢?原因是这样的,Integer
这个类(还有 String
、Double
、Long
等)比较特殊,它是 final
的,是不可变的。当我们使用 num = 2333;
这行代码去赋值的时候发生了什么?
这里我就不画图描述了,这行代码意味着给 num
又创建一个新的对象,所以方法内的 num
引用类型指向了 2333 所处的内存。当我们使用 =
进行操作时候修改的是引用,而不是一个单纯的赋值操作,相当于前面例子中的 myfoo = new Foo("biezhi")
。如果你想实现 Integer
数值的修改可以试试 AtomicInteger
这个类。
小结
一个方法不能修改一个基本数据类型的参数
一个方法可以修改一个对象参数的状态
一个方法不能实现让对象参数引用一个新对象
之前对 Java 中值传递理解不够的原因是没有分清 引用 和 引用传递 是什么,只是在 Java 中理解起来有点绕,通过上面的小示例分析了这些问题出现的原因,如果你还有些模糊也可以参考我下方给出的链接学习,有什么疑问可以留言告诉我。
参考
Is Java “pass-by-reference” or “pass-by-value”?
Java Method Arguments
Java 到底是值传递还是引用传递?
● Java阻塞队列的简单实现
● Spring 的本质系列(1) -- 依赖注入
● java匠人手法-优雅的处理空值
● REST API 的安全基础
● 深入浅出 CAS
● Spring Boot Devtools热部署
● Spring Boot AOP记录用户操作日志
● Spring Boot整合Mongo DB
● 【图文讲解】你一定能看懂的HTTPS原理剖析!
● 基础面试,为什么面试官总喜欢问String?
● Spring Boot Admin 2.2.0发布,支持最新Spring Boot/Cloud之外,新增中文展示!
● 你应该知道的 @ConfigurationProperties 注解的使用姿势,这一篇就够了
如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!
java中date类型如何赋值_Java 中的类型传递问题解惑相关推荐
- JAVA判定参数类型进行赋值_java – 为什么泛型方法在赋值中更改了参数化类型?...
在编写处理表单数据的通用方法时,我遇到了以下(我认为)未完成的行为.给出以下代码: public class Test { public void someGenericMethod(Integer ...
- java date类型大小比较_java中date类型如何比较大小
java中date类型如何比较大小 时间:2018-01-19 来源:Java data类型讲解 Date类在jdk1.1中就已经出现,算得上一个比较有历史的类了,用来表示日期时间.在实际的工 ...
- java怎么给类中的私有变量赋值_Java核心技术笔记分享------第二章 类与对象
对象与类 一.面向对象思想的概述 1>面向对象与面向过程: 二者都是一种思想,面向对象是相对于面向过程而言的.面向过程强调的是功能行为.面向对象,将功能封装进对象,强调具备了功能的对象. 面向对 ...
- java中date如何获取月份_Java:从Date获取月份整数
如何从Date对象(java.util.Date)获取整数作为整数? 实际上,Date上的getMonth()因为永远而被弃用;) @slhck:已弃用. 从JDK 1.1版开始,由Calendar. ...
- java char数组转string数组_Java中char数组(字符数组)与字符串String类型的转换方法...
本文实例讲述了Java中char数组(字符数组)与字符串String类型的转换方法.分享给大家供大家参考,具体如下: 在Java语言编程时,使用"口令字段"jPasswordFie ...
- java 基本类型的引用_Java中的基本数据类型与引用数据类型
一.基本数据类型 byte.short.int.long(整数类型) float.double(浮点数类型) char(字符型) boolean(布尔类型 ) Java数据大多数存放在堆栈中.栈区:存 ...
- java中类型的相互转化_Java中的数据类型及相互转换方法
本文主要讲解两个部分: 一.Java中的数据类型有哪些? 二.数字类型和字符串类型相互转换的方法? 一.Java中的数据类型有哪些: Java中的数据类型有:基本数据类型和引用数据类型: 基本数据类型 ...
- java原始类型和引用类型_Java中的8种原始类型
java原始类型和引用类型 几年前,当我开始编辑Java Basics系列时,我认为将一些非常详细的信息拉到自己的帖子中是很有意义的. 这样,初学者的内容就更容易消化了. 首先,我将介绍有关Java的 ...
- java中object类怎么赋值_Java面向对象之Object类
一.继承体系的老祖宗是Object类.(Object类是所有类的父类) 当我们不希望在程序中某些类被继承,某些方法被重写,某些数据被修订.就是final关键字闪亮登场的时候了. 一个类没有使用exte ...
最新文章
- 新安江遗传算法c语言,基于遗传算法的新安江模型参数优化率定(四)
- DockerCon 2016 深度解读: Citrix 服务发现解决方案 —— Nitrox
- Oracle打开虚拟机闪退,虚拟机上启动Oracle服务为什么自动停止,怎么处理?
- P4827 [国家集训队] Crash 的文明世界
- Android代码数字证书,有关Android中读取证书
- CSS多列布局(实例)
- PHP 函数截图 哈哈哈
- 如何使用开源工具制作YouTube系列
- 【Tools】ubuntu16.04升级Python2.7到3.5
- (20)Xilinx PCIE中断调试成功(学无止境)
- linux 串口命令
- int n=10的sizeof 为什么是四_从int取值范围谈起
- java接口的作用和意义_java什么是接口?接口有什么作用?接口如何使用?
- 年审是当月还是当天_汽车年检提前检车的日期是按原始的还是按检车当月的?...
- iOS开发之开源项目链接
- 【算法】排序_冒泡排序及其优化
- 【MATLAB中UIGETFILE函数的用法】
- IOS下,利用捏合手势实现图像缩放和显示
- 中国的比尔·盖茨-不得不令我佩服了
- Real-time Intended Knee Joint Motion Prediction by deep-recurrent neural networks利用深度递归神经网络实时预测膝关节运动
热门文章
- python文件传输模块_[宜配屋]听图阁 - python 使用poster模块进行http方式的文件传输到服务器的方法...
- 1命名规则 sentinel_SpringCloud Gateway高阶之Sentinel限流、熔断
- linux命令中选项分为,Linux 考试试题
- 大内存 php 干什么好 centos,解决CentOS7中php-fpm进程数过多导致服务器内存资源消耗较大的问题...
- 解决maven打jar包报错:Could not resolve substitution to a value: ${akka.stream.materializer}
- pytorch构造可迭代的DataLoader,动态流式读取数据源,不担心内存炸裂(pytorch Data学习三)
- 青海师大c语言研究生专业课_【考研资讯】多所高校更改专业课科目!考研人还能再怎么惨?...
- 红帽linux免费吗,红帽宣布面向16个系统以下的小型生产环境免费提供RHEL
- 智表ZCELL产品V1.4.0开发API接口文档 与 产品功能清单
- bzoj 4393 Usaco Fruit Feast