【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权)

https://www.cnblogs.com/cnb-yuchen/p/17969159

出自【进步*于辰的博客

1、关于赋值

参考笔记一,P74.1。

一个小结:

所有引用都存于栈,而对象存于堆。引用所指向的可能存于栈,也可能存于方法区常量池。

1.1 基本数据类型赋值

final int a中a是常量,在int a中a是变量。

示例:int a = 10;

a是变量,10是常量(a与10都存于栈)。令a = 20,是将a的值直接由10改为20。

1.2 String类型赋值

String s = "abc"中,s是引用(也是变量,存于栈),"abc"是字符串常量,存于方法区的字符串常量池。令s = "123",是将s由指向"abc"转为指向"123",若"abc"没有其他引用指向就会被回收。

2、关于String赋值

参考笔记一,P74.2。

2.1 情形一

以下两种形式的定义的结果都相同,而底层分析略有不同。

形式一:

示例:

String s1 = "csdn", s2 = "csdn";
s2 = "2023";
sout s1;// 打印:csdn
sout s2;// 打印:2023

若方法区的字符串常量池中存在字符串常量“csdn”,则不会重新创建,直接将s1s2指向“csdn”

s2 = "2023",同样先判断是否存在"2023"。若不存在,则创建,然后将s2由指向"csdn"转为指向"2023"

因此,最终s1指向"csdn"s2指向"2023"

形式二:

示例:

String s1 = "csdn", s2 = s1;
s2 = "2023";
sout s1;// 打印:csdn
sout s2;// 打印:2023

若存在“csdn”,则不会重新创建,直接将s1指向“csdn”,然后将s2指向s1的指向。

后续步骤同上,故结果相同。

这就是为何明明s2 = s1,而s2 = "2023",结果s2改变、s1不变的原因。

2.2 情形二

示例:

String s1 = "csdn", s2 = s1 + "2023", s3 = "csdn2023";
s2.equals(s3);// 结果:true

s2 = s1 + "2023",会先获取s1的指向,是"csdn"

然后为"csdn"复制一个副本,再转为 StringBuffer,后执行append("2023"),最后调用toString(),返回“csdn2023”

此时再判断字符串常量池中是否存在字符串常量"csdn2023",若不存在,则创建,然后将s2指向csdn2023”

因此,s2s3的结果相同。

3、关于String与char[]的比较

如果大家想要了解String类的底层,看这里 → String类。

参考笔记一,P74.3。

示例:

String s1 = "csdn";
char[] arr = {'c', 's', 'd', 'n'};
s1.equals(arr);// 结果:false-------A
s1.toString().equals(arr.toString());// 结果:false-------B
// 注:第一个toString()多余,第二个toString()是在底层调用
// 我这么写是为了方便大家理解

String类重写了equals(),在底层会先调用toString(),返回值后再判断;而char[]不是具体类型,不存在重写。当然,仍会调用toString(),即示例中的A与B等效,但调用的是Object类的toString()(返回地址),故不等。

4、不同类型引用分析

参考笔记一,P36.5;笔记二,P38.1。

4.1 int

示例:

int a = 100, b = a;

a、b、100都存于栈,令a = 20,是直接将a的值改为20,b的值仍为100。

4.2 Integer

关于八位有符号二进制的表示范围,可查阅博文《关于二进制的原码、补码和反码,以及表示范围、常见位运算符和进制转换的理解与简述》的第1.2项。

Integer 类的“自动装箱”和“自动拆箱”机制是什么?

  1. 包装类都具有自动装箱和自动拆箱的功能(以代码的角度上说,就是会在底层调用某个方法)。
  2. 为包装类Integer赋值时,自动装箱是底层调用了valueOf()。这里存在一个溢出问题。因为整型常量存储于方法区的整型常量池,而整型常量池使用8位有符号二进制表示整型。8位有符号二进制的表示范围是-128 ~ 127。若整型超出此此范围,就是“溢出”。
  3. “溢出”规定:若整型在范围内,valueOf()底层创建整型常量,存储于整型常量池;否则创建 Integer 对象,存储于堆。

示例:

关于valueOf(),可参考Integer类的第4.33项。

Integer i1 = 1;
Integer i2 = new Integer(1);
Integer i3 = Integer.valueOf(1);
i1 == i2;// false
i1 == i3;// true
i2 == i3;// false Integer i4 = 128;
Integer i5 = new Integer(128);
Integer i6 = Integer.valueOf(128);
i4 == i5;// false
i4 == i6;// false
i5 == i6;// false

底层分析:

  • i1指向整型常量1i2指向new Integer(1);由于1在表示范围内,故valueOf(1)返回整型常量1,则i3也指向整型常量1
  • 由于整型常量池仅能存储-128 ~ 127的整型常量,故i4指向new Integer(128)i5指向new Integer(128);由于128超出表示范围,故valueOf(128)返回new Integer(128)

扩展一点:

i1.equals(i2);// true
i1.equals(i3);// true
i2.equals(i3);// true i4.equals(i5);// true
i4.equals(i6);// true
i5.equals(i6);// true

为何结果都为true

关于equals(),可参考Integer类的第4.6项。

4.3 int[]

示例:

int[] arr1 = {1, 2, 3}, arr2 = arr1;

arr1arr2以及数组内所有的值都存于栈,{1, 2, 3}存储于堆。

arr1[0] = 10,是直接将1改为10,则arr1是{10, 2, 3};arr2与arr1指向相同,故arr2也是{10, 2, 3}

4.4 Integer[]

示例:

Integer[] arr1 = {1, 2, 3}, arr2 = arr1;

int[]不同的是,Integer[]内的所有元素都不是直接的值,而是引用,并且是 Integer 引用,指向整型常量池或堆。

不过,无论指向哪里,由于arr2与arr1始终指向相同,因此,令arr1[0] = 10,则arr1是{10, 2, 3},arr2同样是{10, 2, 3}

5、最后

本文中的例子是为了方便大家理解java基本数据类型和引用类型赋值时的底层而简单举例的,不一定有实用性。

PS:

大家在看完这篇文章后肯定想吐槽:“你说了这么多,示例结果还不是与我们平时使用时的结果无差别,有什么意义。”

哈哈......结果当然相同了,因为我阐述的是底层分析。这些呢在平时工作中一般是用不到的,因此,目的是为了让大家对java基本数据类型和引用类型赋值时的底层有进一步的理解。

本文完结。

[Java]基本数据类型与引用类型赋值的底层分析的小结的更多相关文章

  1. Java之数据类型,变量赋值

    Java中的基础数据类型(四类八种): 1.整数型 byte----使用byte关键字来定义byte型变量,可以一次定义多个变量并对其进行赋值,也可以不进行赋值.byte型是整型中所分配的内存空间是最 ...

  2. java原生数据类型和引用类型

    java 中String 是个对象,是引用类型基础类型与引用类型的区别是,基础类型只表示简单的字符或数字,引用类型可以是任何复杂的数据结构基本类型仅表示简单的数据类型,引用类型可以表示复杂的数据类型, ...

  3. java基本数据类型和引用类型

    这些基本的数据类型是点不出东西来的 3种引用类型  类class 接口interface 数组array 第一个  : 类 Integer  Long  Boolean  Byte  Characte ...

  4. java基本数据类型与引用类型

    基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768~3 ...

  5. Java基本数据类型之间赋值与运算归纳

    前言:面对“byte b1=3;byteb2=7;byte b=b1+b2;”报错,而“int i1=3;int i2=7;int i=i1+i2;”不报错,进行了深入探究,从而引申出java基本类型 ...

  6. Java中的基本数据类型和引用类型

    一.基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768 ...

  7. Java中构造函数传参数在基本数据类型和引用类型之间的区别

    Java中构造函数传参数在基本数据类型和引用类型的区别 如果构造函数中穿的参数为基本数据类型,如果在函数中没有返回值,在调用的时候不会发生改变:而如果是引用类型,改变的是存储的位置,所有不管有没有返回 ...

  8. Java基本数据类型总结

    基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型.它们是我们编程中使用最频繁的类型.java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量的初始化. 1. Java ...

  9. Java基本数据类型及其封装器的一些千丝万缕的纠葛

    一些概念     想必大家都知道Java的基础数据类型有:char.byte.short.int.long.float.double.boolean 这几种,与C/C++等语言不同的是,Java的基础 ...

  10. Java基本数据类型总结(转载)

    Java基本数据类型总结 基本类型,或者叫做内置类型,是JAVA中不同于类的特殊类型.它们是我们编程中使用最频繁的类型.java是一种强类型语言,第一次申明变量必须说明数据类型,第一次变量赋值称为变量 ...

随机推荐

  1. 计网学习笔记四 Bridge && Switch

    在前面的学习中,我们学习了MAC和LAN.在一个LAN里可以通信是很不错的,我们可以用一些东西让它变得更加不错!那就是我们接下来学习的网桥和交换机,其中包括了一点802.1D机制. Bridge 网桥 ...

  2. 建立DNS隧道绕过校园网认证

    建立DNS隧道绕过校园网认证 因为之前在本科的时候破解过校园网三次,主要就是利用其业务逻辑上的漏洞.53端口未过滤包.重放攻击的手段,然后就是一个博弈的过程,这三次加起来用了大概有一年的时间就被完全堵 ...

  3. pycharm—flask创建简单web项目

    1.系统 系统 版本 OS win 10 pycharm 专业版2022.3.1 2.引入flask包 pip install flask 3.项目目录展示.代码.浏览器访问 from flask i ...

  4. 机器学习策略篇:详解为什么是ML策略?(Why ML Strategy?)

    为什么是ML策略? 从一个启发性的例子开始讲,假设正在调试的猫分类器,经过一段时间的调整,系统达到了90%准确率,但对的应用程序来说还不够好. 可能有很多想法去改善的系统,比如,可能想去收集更多的训练 ...

  5. python项目vscode配置

    最近由pycharm切到VScode, 记录一下项目的通用配置; 在项目目录建一个.vscode的文件夹分别创建三个文件 lunch.json python运行配置 settings.json vsc ...

  6. ASP.NET Core MVC应用模型的构建[1]: 应用的蓝图

    我个人觉得这是ASP.NET Core MVC框架体系最核心的部分.原因很简单,MVC框架建立在ASP.NET Core路由终结点上,它最终的目的就是将每个Action方法映射为一个或者多个路由终结点 ...

  7. mysql分组后获取每个组排序后的第一条数据(整行)

    有一个学生分数表student,数据结构是这样的 CREATE TABLE `student` ( `id` int(11) NOT NULL, `student_id` int(11) DEFAUL ...

  8. 案例分享:Qt出版社书籍配套U盘资源播放器软件定制(脚本关联播放器与资源文件,播放器,兼容win7,win10和mac)

    红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术.树莓派.三维.OpenCV.OpenGL.ffmpeg.OSG.单片机.软硬结合等等)持续更新中-(点击传送门) 合作案例专栏:案例分享(体 ...

  9. django学习第十四天--Forms和ModelForm

    Forms和ModelForm 进行数据校验,先看数据校验的过程 注册页面图解: 前端为了用户体验会做一些校验,不满足校验要求会报错 服务端也会对数据进行一些校验,不满足校验要求会报错 数据库也会对数 ...

  10. 【LeetCode二叉树#02】二叉树层序遍历(广度优先搜索),十合一专题

    二叉树层序遍历(广度优先搜索) 102 二叉树的层序遍历 力扣题目链接(opens new window) 给你一个二叉树,请你返回其按 层序遍历 得到的节点值. (即逐层地,从左到右访问所有节点). ...