首页 > 编程语言 >春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了

春眠不觉晓,Java数据类型知多少?基础牢不牢看完本文就有数了

时间:2024-01-13 15:44:25浏览次数:40  
标签:牢不牢 Java int 数据类型 包装 类型 Integer

文编|JavaBuild

哈喽,大家好呀!我是JavaBuild,以后可以喊我鸟哥!俺滴座右铭是不在沉默中爆发,就在沉默中灭亡,一起加油学习,珍惜现在来之不易的学习时光吧,等工作之后,你就会发现,想学习真的需要挤时间,厚积薄发啦!

我们知道Java是面向对象的静态型编程语言,在Java的世界里万物皆对象。但我认为是万物皆数据,世界由各种各样数据构建起来,我们通过程序去实现数据的增删改查、转入转出、加减乘除等等,不同语言的实现方式殊途同归。
由此可见,数据对于程序语言的重要性,而在Java中用来规范数据的标准我们将其称之为“数据类型”,这便是我们今天的Topic!
在下图中我们将Java中的数据类型分为三个部分:基本数据类型包装类型引用数据类型

基本数据类型

在Java中“boolean、char、byte、short、int、long、float 和 double”构建起了数据结构的基础,非常重要,也是很多公司面试的高频考点,所以,为了方便记忆,鸟哥整理了一份表格如下:

类型名称 位数 字节 默认值 取值范围 包装类 缓存区间
byte 8 1 0 -128 ~ 127 Byte -128~127
short 16 2 0 -32768 (-2^15) ~ 32767 (2^15-1) Short -128~127
int 32 4 0 -2147483648 ~ 2147483647 Integer -128~127
long 64 8 0L -2^63 ~2^63 - 1 Long -128~127
char 16 2 '\u0000' 0~65535 Character 0 ~127
float 32 4 0f 1.4e-45 ~ 3.4e+38 Float
double 64 8 0d 4.9e-324~1.798e+308 Double
boolean 1 false true(1),false(0) Boolean

字节与位的关系

在计算机的物理存储中,一条电路线被称之为1位,二进制识别中为0(低电平)或1(高电平),英文中用bit表示,而8个bit组成一个字节,英文为Byte

布尔类型的说明

对于 boolean,官方文档未明确定义,它依赖于 JVM 厂商的具体实现。逻辑上理解是占用 1 位,但是实际中会考虑计算机高效存储因素。

基本数据类型之间的转换规则

基本数据类型之间也存在着转换关系,往往发生在表达式计算的过程中,而这种转换根据不同场景分为:自动类型转换&强制类型转换
自动类型转换:Java编译器无需显示处理,一般由等级低的数据类型向等级高的数据类型转换,如int -> long。很明显,int所能存储的数据必定是long的子集,不存在数据丢失问题。

等级由低到高
byte -> short -> int -> long -> float -> double
char -> int -> long -> float -> double
int a = 3;
double b = 1.5;
// 自动类型转换:a 被转换为 double 类型
double result = a * b;
System.out.println("结果: " + result); // 输出:结果: 4.5

强制类型转换:由高等级数据转为低等级数据时往往存在强制类型转换,这时候Java编译器认为存在隐患,需要程序员介入,显示的处理强转,潜在风险是数据丢失或精度丢失。

由左到右需要强转
double -> float -> long -> int -> char -> short -> byte
double c = 10.1;
// 强制类型转换:将 double 类型转换为 int 类型,精度丢失
int d = (int) c;
System.out.println("整数值: " + d); // 输出:整数值: 10

转换规则如下

= 右边先自动转换成表达式中最高级的数据类型,再进行运算。整型经过运算会自动转化最低 int 级别,如两个 char 类型的相加,得到的是一个 int 类型的数值。
= 左边数据类型级别 大于 右边数据类型级别,右边会自动升级
= 左边数据类型级别 小于 右边数据类型级别,需要强制转换右边数据类型
char 与 short,char 与 byte 之间需要强转,因为 char 是无符号类型

包装类型

这八种基本类型都有对应的包装类分别为:Byte、Short、Integer、Long、Float、Double、Character、Boolean 。
因为Java中一切皆对象,基本数据类型无法满足这个大口号,比如泛型、序列化、类型转换、高频数据区间的缓存等,故为了弥补,便诞生了8种基本数据类型对应的包装类型。

包装类型与基本数据类型差异

  • 使用场景: 在Java中除了一些常量和局部变量的定义会用到基础数据类型外,绝大部分情况下均采用包装类型,如方法参数,对象属性等,且基本数据类型不能用于泛型,包装类型可以!
  • 默认值: 包装类型比基本类型多了一个非功能值:null,在不做任何赋值的情况下,包装类型的默认就是null,而基本数据类型都有相应的默认值,见上面表格。
  • 所占内存 因为包装类型是对象,会有一些对象头等信息,所以占用空间上要大于基本数据类型。
  • 比较方式 基本类型采用 == 号比较,比较的是值,而对于包装类型来说,==比较的其实是对象的内存地址,对象值的比较需要通过equals()方法完成。

[注意]: 很多同学都以为基本数据类型存在栈中,包装类型作为对象存储在堆中,这个观点是有失偏颇的,如果基础数据类型的成员变量在没有被static关键字修饰的情况下,是存在的堆中的,只有局部变量被存在栈的局部变量表中!而全部对象都存在堆中,也是个不完整的答案,这里涉及到HotSpot中的逃逸分析,等讲到JVM时再展开说吧。

自动装箱与拆箱

在Java中不仅仅基本类型之间存在着转换,基本数据类型与包装类型之间同样存在着转换,在JDK1.5之前是不支持自动装箱与拆箱的,所以那时候需要通过显示的方法调用来实现转换,而JDK1.5开始,自动化程度提升了。
装箱:基本类型转变为包装器类型的过程。
拆箱:包装器类型转变为基本类型的过程。

//JDK1.5之前是不支持自动装箱和自动拆箱的,定义Integer对象,必须
Integer i = new Integer(8);
 
//JDK1.5开始,提供了自动装箱的功能,定义Integer对象可以这样
Integer i = 8;
int n = i;//自动拆箱

实现原理

装箱是通过调用包装器类的 valueOf 方法实现的
拆箱是通过调用包装器类的 xxxValue 方法实现的,xxx代表对应的基本数据类型。
如int装箱的时候自动调用Integer的valueOf(int)方法;Integer拆箱的时候自动调用Integer的intValue方法。

【需要注意的问题点】:
1、整型的包装类 valueOf 方法返回对象时,在常用的取值范围内,会返回缓存对象。
2、浮点型的包装类 valueOf 方法返回新的对象。
3、布尔型的包装类 valueOf 方法 Boolean类的静态常量 TRUE | FALSE。

Integer i1 = 100;
Integer i2 = 100;
Integer i3 = 200;
Integer i4 = 200;

System.out.println(i1 == i2);//true
System.out.println(i3 == i4);//false
        
Double d1 = 100.0;
Double d2 = 100.0;
Double d3 = 200.0;
Double d4 = 200.0;
System.out.println(d1 == d2);//false
System.out.println(d3 == d4);//false
        
Boolean b1 = false;
Boolean b2 = false;
Boolean b3 = true;
Boolean b4 = true;
System.out.println(b1 == b2);//true
System.out.println(b3 == b4);//true

以上代码中,我们已Integer为例展开解释一下,基本数据类型的包装类除了 Float 和 Double 之外,其他六个包装器类(Byte、Short、Integer、Long、Character、Boolean)都有常量缓存池。而Integer的缓存区间是-128~127。
我们去看一下Integer类的缓存源码

public static Integer valueOf(int i) {
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}
private static class IntegerCache {
    static final int low = -128;
    static final int high;
    static {
        // high value may be configured by property
        int h = 127;
    }
}

IntegerCache 这个静态内部类中设置了缓存区间,当我们通过valueOf()方法获取Integer对象时,会先去找该整数是否在缓存池中,有则直接返回,没有则新建并存入缓存池。
这就解释了为什么第一个 == 号结果是true,而第二个为false,因为超出了缓存区间,每次都新建一个对象,而 == 号又是比较对象地址,对于两个不同的对象,地址肯定不一样啦。

引用数据类型

Java的数据类型除了8种基本数据类型和对应的包装类型外,还有一个分类为引用数据类型,在文章开头的树形图中已经分好,引用类型分为:数组,类和接口。
那为什么叫他引用数据类型呢?在创建引用数据类型时,会在栈上给其引用句柄,分配一块内存,然后对象的信息存储在堆上,在程序调用的时候,通过栈上的引用句柄指向堆中的对象,从而获取想要的数据。
因数组,类,接口都包含着太多内容,在后续的博客中会陆续详解,所以本文略做介绍,粗略感受一下。
数组:

int [] arrays = {1,2,3};
System.out.println(arrays);
// 打印结果:[I@2d209079

打印结果中的一串内容,世界上是arrays的对象首地址,要想看到结果,需要调用java.lang.Object 类的 toString() 方法。
类:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];
}

String是一个类,也是字符串的代表,所以它也是引用数据类型
接口:

List<String> list = new ArrayList<>();
System.out.println(list);

List 是一个非常典型的接口,属于Java的一种集合,存储的元素是有序的、可重复的。

【注意】

1、包装类可以实现基本类型和字符串之间的转换,字符串转基本类型:parseXXX(String s);基本类型转字符串:String.valueOf(基本类型)。
2、引用数据类型的默认值为 null,包括数组和接口。
3、char a = 'h'char :单引号,String a = "hello" :双引号。

标签:牢不牢,Java,int,数据类型,包装,类型,Integer
From: https://www.cnblogs.com/JavaBuild/p/17962423

相关文章

  • idea 中java代码修改后运行代码不生效
    背景在使用idea开发项目过程中,经常会多版本切换开发,有时在一个分支中提交代码修改后,重新运行项目还是之前版本的项目,修改没有生效解决方案方案一依赖的模块版本不变,只修改了代码没有及时打到本地库。可以对依赖的模块执行mvncleaninstall后重新运行项目方案二原先的项目......
  • 详解Java信号量-Semaphore
    第1章:引言大家好,我是小黑。今天,咱们一起来深入探讨一下Semaphore。在Java中,正确地管理并发是一件既挑战又有趣的事情。当谈到并发控制,大家可能首先想到的是synchronized关键字或者是ReentrantLock。但其实,Java还提供了一个非常强大的工具,就是Semaphore。Semaphore,直译过来就是......
  • JavaScript学习之旅——初识
    JavaScript学习之旅——初识本文内容基于JavaScript相关基础知识进行介绍JavaScript学习之旅——初识前言一、JavaScript是什么(都有什么呢?)1.ECMAScript2.WebAPIs二、JavaScript的书写位置1.内部JavaScript2.外部JavaScript3.内联(行内)JavaScript4.JavaScript语句结束符三、......
  • 【Linux】Java文件IO之普通IO与Buffer IO
    在Java中,输入输出(IO)操作是编程中一项重要的任务。无论是从外部文件中读取数据,还是向文件写入数据,或者是与用户进行交互,都需要用到IO操作。普通IOFileOutputStream的使用FileOutputStream是Java中的一个类,属于java.io包。它用于将数据写入文件。当你需要将数据(通常是字节或字符)写入......
  • 【flink番外篇】9、Flink Table API 支持的操作示例(14)- 时态表的join(java版本)
    文章目录Flink系列文章一、maven依赖二、时态表的join1、统计需求对应的SQL2、Withoutconnnector实现代码3、Withconnnector实现代码1)、bean定义2)、序列化定义3)、实现本文通过两个示例介绍了时态表TemporalTableFunction的join操作。本文除了maven依赖外,没有其他依赖。一、m......
  • Invalid value type for attribute ‘factoryBeanObjectType‘: java.lang.String
    ErrorstartingApplicationContext.Todisplaytheconditionevaluationreportre-runyourapplicationwith'debug'enabled.2024-01-05T17:04:00.527+08:00ERROR201118---[solve][main]o.s.boot.SpringApplication:Appli......
  • 《Java编程思想第四版》学习笔记53--关于UDP
    1、TCP和UDP端口是相互独立的。也就是说,可以在端口8080同时运行一个TCP和UDP服务程序,两者之间不会产生冲突。P.547//:Dgram.java//Autilityclasstoconvertbackandforth//BetweenStringsandDataGramPackets.importjava.net.*;publicclassDgram{publ......
  • Java日期时间处理详解
    Java中SimpleDateFormat、LocalDateTime和DateTimeFormatter的区别及使用在Java的世界里,处理日期和时间是常见的任务。尤其在Java8之前,SimpleDateFormat是处理日期和时间的主要方式。然而,Java8引入了新的日期时间API,其中LocalDateTime和DateTimeFormatter成为了新的选择。本文......
  • 详解Java多线程之循环栅栏技术CyclicBarrier
    第1章:引言大家好,我是小黑,工作中,咱们经常会遇到需要多个线程协同工作的情况。CyclicBarrier,直译过来就是“循环屏障”。它是Java中用于管理一组线程,并让它们在某个点上同步的工具。简单来说,咱们可以把一群线程想象成一队马拉雪橇的驯鹿,CyclicBarrier就像是一个指定的集合点,所有驯......
  • java项目(jar包)配置为开机自启 jar包bat脚本启动和配置为开机自启
    今天给大家分享一下,如何把java项目,打包--------打包后启动---------生成bat文件启动-----------设置为开机自启。每一步都是先是文字描述,后面是图片展示。首先是打包,咱们写好的项目在maven处点击clear,等待完成后,点击package      打包完成后,在target目录下可以看到......