Java内存管理-你真的理解Java中的数据类型吗(十)

勿在流沙筑高台,出来混迟早要还的。做一个积极的人编码、改bug、提升自己我有一个乐园,面向编程,春暖花开!作为Java程序员,Java 的数据类型这个是一定要知道的! 但是不管是那种数据类型最终存储都要到内存中,本文由浅入深对数据类型进行介绍和讲解,相信读完本文你一定会有收获的,会对Java数据类型有更深的了解和认识!本文地图一、什么是位、字节、字符、字符集位(bit):计算机…

大家好,又见面了,我是全栈君。

做一个积极的人

编码、改bug、提升自己

我有一个乐园,面向编程,春暖花开!

推荐阅读

第一季

0、Java的线程安全、单例模式、JVM内存结构等知识梳理
1、Java内存管理-程序运行过程(一)
2、Java内存管理-初始JVM和JVM启动流程(二)
3、Java内存管理-JVM内存模型以及JDK7和JDK8内存模型对比总结(三)
4、Java内存管理-掌握虚拟机类加载机制(四)
5、Java内存管理-掌握虚拟机类加载器(五)
6、Java内存管理-类加载器的核心源码和设计模式(六)
7、Java内存管理-掌握自定义类加载器的实现(七)
第一季总结:由浅入深JAVA内存管理 Core Story

第二季

8、Java内存管理-愚人节new一个对象送给你(八)
【福利】JVM系列学习资源无套路赠送
9、Java内存管理-”一文掌握虚拟机创建对象的秘密”(九)
10、Java内存管理-你真的理解Java中的数据类型吗(十)
11、Java内存管理-Stackoverflow问答-Java是传值还是传引用?(十一)
12、Java内存管理-探索Java中字符串String(十二)

实战

一文学会Java死锁和CPU 100% 问题的排查技巧

分享一位老师的人工智能教程。零基础!通俗易懂!风趣幽默!
大家可以看看是否对自己有帮助,点击这里查看【人工智能教程】。接下来进入正文。

勿在流沙筑高台,出来混迟早要还的。

作为Java程序员,Java 的数据类型这个是一定要知道的! 但是不管是那种数据类型最终存储都要到内存中,本文由浅入深对数据类型进行介绍和讲解,相信读完本文你一定会有收获的,会对Java数据类型有更深的了解和认识!

本文地图

Java内存管理-你真的理解Java中的数据类型吗(十)

一、什么是位、字节、字符、字符集

位(bit):计算机内部存储数据的最小单位,音译为比特,每个二进制数字0或者1就是1个位!

字节(Byte):计算机**存储容量(数据处理)**的基本单位,音译拜特,8个位构成一个字节;即:1 byte (字节)= 8 bit(位)。

一个字节能够存放的数字范围用二进制表示为00000000011111111,也就是8个bit(比特),8个比特转换为无符号的10进制数字范围是0255,转换为有符号数据一般为-128~127。


字节说明:对于存储容量,我们是比较熟悉的,计算机存储容量大小以字节数来度量,1024进位制:

1024B=1K(千)B (1024个字节等于 1KB)
1024KB=1M(兆)B
1024MB=1G(吉)B
1024GB=1T(太)B
还有PB、EB、ZB、YB 、NB、DB等

字符:字符是一种符号,同以上说的存储单位不是一回事。指计算机中使用的字母、数字、字和符号,包括:1、2、3、A、B、C、~!·#¥%……—*()——+等等。字符一般在不同的编码(字符集)下面占用的字节数不同!也即占用存储空间不同!

编码:编码就是一个编号(数字)到字符的一种映射关系(集合),常见的有 ASCII、ISO-8859-1、GB2312、GBK、UTF-8、UTF-16 等。它们都可以被看作为字典,它们规定了转化的规则,按照这个规则就可以让计算机正确的表示我们的字符。

# 简单举例举例:
在 ASCII 编码中,一个英文字母字符存储需要1个字节。
在 GB 2312 编码或 GBK 编码中,一个汉字字符存储需要2个字节。
在UTF-8编码中,一个英文字母字符存储需要1个字节,一个汉字字符储存需要34个字节。
在UTF-16编码中,一个英文字母字符或一个汉字字符存储都需要2个字节(Unicode扩展区的一些汉字存储需要4个字节)。
在UTF-32编码中,世界上任何字符的存储都需要4个字节。

tips:

ASCII码是最熟知字符编码,编码范围为0255,属于单字节编码。ASCII码编码范围太小了,Java为了能够处理多字节语言编码(比如中文、日文、韩文等)编码范围0x0000000x10FFFF,采用国际组织制定的Unicode编码集。

因为Unicode编码并非连续的,所有将Unicode转换为具体的数值格式是又有多种不同的转换方式。称为Unicode Translation Format(UTF)。

简单总结一下UTF-8、UTF-16、UTF-32三种转换方式,都是采用字节作为编码的基本单位!

转换方式 特点 优点 缺点
UTF-8 变长编码,1-4字节 节省空间 转换麻烦
UTF-16 固定编码,2字节 转换相对简单 空间相对节省
UTF-32 固定编码,4字节 转换简单 空间最浪费

目前使用UTF-8还是比较多,节省空间还是很大的优势! 在说明一点Java虚拟机内部使用的UTF-16转换方式,固定使用两个字节,所以java中字符char 占用 2个字节!


编码这一块的内容其实挺多,如需了解更多深入细节,请自行查阅相关资料!

二、基本数据类型和引用数据类型

有学过C语言的伙伴知道在C语言中可以声明指针类型的变量,但是在Java语言中是看不到使用指针的,那么Java中有没有指针呢?准确的话是有的,因为在Java底层有些类型是封装了指针的。在Java中根据底层是否封装了指针可以将Java的数据类型分为两类,值类型和引用类型

数据类型

2.1、值类型

值类型: 也称为基本数据类型和基元数据类型。它的值就是一个数字,一个字符或一个布尔值等。

没有封装指针的变量,它们在Java中有8个,包括bytecharshortintfloatlongdoubleboolean

这些基本类型首字母都是小写,它们并不是类,也没有属性和方法。声明值类型变量,只会在中分配一块内存空间。

值类型

这里面还有一个知识点是: 自动类型转换强制类型转换

自动类型转换

一般情况下Java中会将占用内存空间较低的类型转换为较高类型,如 int型的变量和 long型的变量进行计算的时候,会将int型转换为long型;

如果两个变量占用内存空间一样,但是一个是整型,一个是浮点型,则会将整型转换为浮点型。如int型变量与float型变量进行计算,会将int型转换为float型。

强制类型转换:

第一种情况:提升变量的类型级别,以获取精度更高的计算结果! 比如 两个整型int变量进行除法运算,为了精度更高,强制转为long类型!

第二种情况:需要用占用空间较小的变量类型接受占用空间较大的变量类型。比如 int转为byte等,但是要注意 转换过程中产生溢出截断的情况!

上面图中内容中没有boolean类型变量进行说明,因为boolean类型比较特殊。boolean类型变量只有两个值,true或者false,它不参与数学运算,也不能与其他类型变量进行转换(不管自动转换还是强制转换),只是用来进行逻辑判断。

boolean类型变量的内存空间占用具有一定的不确定性,理论上一个比特就可以保存boolean类型变量的值,当因为内存使用的最小单位是字节,那么变量不可能仅占用1/8个字节。实际中,根据编译器的不同,**Java会使用1~4字节来保存boolean变量。**字节内容均为0表示false。只要有字节为非0值表示true。

面试一定要注意 :String 不是基本类型!

2.2、引用类型

引用类型: 就是底层封装指针的数据类型。这部分包含的比较多,比如我们自定义或者系统的、抽象类、接口,以及数组。它们在内存中分配两块空间,首先要在栈上给其引用(句柄)分配一块内存(不存放具体数值),然后对象的具体信息都存储在堆内存上(如对象的属性值等),最后由栈上面的引用指向堆中对象的地址。

2.3、简单示例

示例代码:

public class PrettyGirl { 
   
    /** * 姑娘姓字名谁 */
    String name;

    /** * 芳龄几何 */
    int age;

    public static void main(String[] args) { 
   
        // PrettyGirl是自定义类,是引用类型,分配两块内存空间
        PrettyGirl prettyGirl = new PrettyGirl();

        // String类是系统类,也是引用类型,分配两块内存空间
        String name = new String("Java ok");

        // int,float 是值类型,只分配一块内存空间
        int num = 10;
        float price = 110.10f;

        // 对象名.属性名访问对象的属性,访问包括赋值和取值
        prettyGirl.name = "Alice";
        prettyGirl.age = 25;

    }

}

通过类名 对象名 = new 类名()创建对象, 在 PrettyGirl prettyGirl = new PrettyGirl();这行代码在内存中就创建了两块内存空间,第一块在栈中,名字叫 prettyGirl,它是一个引用地址,并不放具体的数值,第二块堆中的内存才存放具体的数值,如name,age等信息。

Java内存管理-你真的理解Java中的数据类型吗(十)

其实数组内部也是封装引用(指针),即便是基本类型的数组,也是如此! **数组也是引用类型!**比如

int[] nums = new int[]{ 
   1,4,7,3,9};

Java内存管理-你真的理解Java中的数据类型吗(十)

说明 :0x001 是我随便写的一个值,真实的内存地址并不是这个,这个值只是为了我画图方便!

在多强调一点,在引用类型中,对于类来说,要创建对象其实包括两步,第一是声明对象,第二是创建对象!

public static void main(String[] args) { 
   
    // 声明对象,相当分配指针类型变量,在栈中分配内存
    PrettyGirl alice;
    // 创建对象,创建具体内存空间,在堆中分配内存
    alice = new PrettyGirl();
}

声明对象:就相当于在栈中声明引用类型的变量,它的内存不存放具体的数值,而只存放另一块堆中内存的地址!如

PrettyGirl alice;

创建对象:一般使用new关键字,如下代码

alice = new PrettyGirl();

上面这一行代码做了两件事情,首先在堆中分配一块存放具体数值的内存,然后将这个内存的首地址赋给上面声明的引用变量!

Java内存管理-你真的理解Java中的数据类型吗(十)

其实很多时候,对象的声明和创建是放在一行的,如下:

PrettyGirl mary = new PrettyGirl();

三、 八种基本类型的包装类和常量池

以下内容摘自:参考资料1 中 8种基本类型的包装类和常量池部分内容!

Java 基本类型的包装类的大部分都实现了常量池技术,即Byte,Short,Integer,Long,Character,Boolean;这5种包装类默认创建了数值[-128,127]的相应类型的缓存数据,但是超出此范围仍然会去创建新的对象

两种浮点数类型的包装类 Float,Double 并没有实现常量池技术。

Integer i1 = 33;
Integer i2 = 33;
System.out.println(i1 == i2);// 输出true
Integer i11 = 333;
Integer i22 = 333;
System.out.println(i11 == i22);// 输出false
Double i3 = 1.2;
Double i4 = 1.2;
System.out.println(i3 == i4);// 输出false, 无缓存!

Integer 缓存源代码:

/** *此方法将始终缓存-128到127(包括端点)范围内的值,并可以缓存此范围之外的其他值。 */
public static Integer valueOf(int i) { 
   
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

对于Integer类型来说,值在-128-127,用==比较是一致的,超过这个区间就不行了。

应用场景:

  1. Integer i1=40;Java 在编译的时候会直接将代码封装成Integer i1=Integer.valueOf(40);,从而使用常量池中的对象。
  2. Integer i1 = new Integer(40);这种情况下会创建新的对象。
Integer i1 = 40;
Integer i2 = new Integer(40);
System.out.println(i1==i2);//输出false

最后在贴出阿里巴巴Java手册中对包装类使用的建议:

Java内存管理-你真的理解Java中的数据类型吗(十)

四、本文总结

本文整体内容相对基础,但是在java开发中还是非常重要,注重细节和基础,让写出的每一行代码都是最优的!朝着这个方向努力! 下一篇整理一下值传递和引用传递! 敬请期待!

备注: 由于本人能力有限,文中若有错误之处,欢迎指正。

五、参考资料

1、可能是把Java内存区域讲的最清楚的一篇文章

2、Java语言中一个字符占几个字节?


谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞或者喜欢,让更多的人看到!祝你每天开心愉快!



Java编程技术乐园:一个分享编程知识的公众号。跟着老司机一起学习干货技术知识,每天进步一点点,让小的积累,带来大的改变!


扫描关注,后台回复【资源】,获取珍藏干货! 99.9%的伙伴都很喜欢

image.png | center| 747x519


©
每天都在变得更好的阿飞云

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/121026.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 安卓手机如何打开.pdf(1)文件_手机pdf格式怎么使用查找功能

    安卓手机如何打开.pdf(1)文件_手机pdf格式怎么使用查找功能最近在做结算功能,需要上传发票功能,发票有电子和图片发票两种,技术这边有两种方案,一种是上传图片文件,还有一种是上传PDF格式发票文件,但是结算时财务说图片文件上面没有公司盖章,是无效的,于是把方案改为电子发票PDF和纸质发票,刚开始使用的文件管理器搜索手机内的PDF文件,在4.4系统上面打开文件管理器可以过滤掉非.pdf格式文件,在6.0及以上系统没有过滤掉,用的是intent打开u…

  • vue-cli构建vue项目

    vue-cli构建vue项目

  • Postgresql动态SQL

    Postgresql动态SQLPostgreSQL支持动态SQL,以PL/Pgsql为例,语法如下:EXECUTEcommand-string[INTO[STRICT]target][USINGexpression[,…]];上式中的可选项target表示arecordvariable,arowvariable,oracomma-separatedlistofsimplev…

  • python之turtle海龟绘图篇[通俗易懂]

    python之turtle海龟绘图篇[通俗易懂]海龟绘图,想什么,画什么:七段数码管、谢尔帕斯基三角形、玫瑰花和小猪佩奇都不是问题

  • 如何用51单片机控制步进电机运动「建议收藏」

    如何用51单片机控制步进电机运动「建议收藏」本来接触单片机挺久了的,但是一直只是停留在非常初级的认识阶段,本科的时候上过几门课,但是从来没有自己捣鼓过单片机,这次突然来了兴趣,感觉一下子学到了好多东西,在这里好好整理一下。这篇文章只适合于入门阶段的小白阅读,高手请绕道。12年年初的时候购买了一套普中科技的“单片机开发试验仪”,好多次想好好学学,结果每一次都半途而废,主要原因还是周围的人都不会用,有问题都不知道找谁问,结果锁到箱子里一直到现在。

  • pycharm导入自定义模块_模块导入速度python

    pycharm导入自定义模块_模块导入速度pythonPycharm是很多Python开发者的首选IDE,如果能把一个工具熟练运用,往往有事半功倍的效果,各种快捷键、重构功能、调试技巧。由于Python是一门动态语言,对于自动导入包模块没有静态语言那么方便,但是我们有了Pycharm,还是可以很强大的。平时写代码的时候,要引用系统自带的模块或者是第三方模块,甚至是项目中其它地方的模块,有时候代码快写了一整屏,为了把一个模块导入进来,我们不得不把光标

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号