Java基础——数据类型

数据类型

基本数据类型

JAVA中一共有八种基本数据类型:
byte、short、int、long、float、double、char、boolean

类型 类别 字节 取值范围
byte 整型 1byte -27 ~ 27-1
short 整型 2byte -215 ~ 215-1
int 整型 4byte -231 ~ 231-1
long 整型 8byte -263 ~ 263-1
float 浮点型 4byte 3.402823e+38 ~ 1.401298e-45
double 浮点型 8byte 1.797693e+308~ 4.9000000e-324
char 文本型 2byte 0~216-1
boolean 布尔型 1byte true/false

要点:

  • 整数值默认为int类型
  • 小数默认是double类型
  • 浮点型的数据是不能完全精确的
  • String不是基本数据类型
  • 整数的最高位为符号位

  Java虚拟机中所支持的与数据类型相关的字节码指令中,大部分都没有支持整数类型的byte、char、和short,甚至没有任何指令支持boolean类型。编译器会在编译期或运行期将byte和short类型的数据带符号扩展为相应的int类型数据,将boolean和char类型数据零位扩展为相应的int类型数据。与之类似的,在处理Boolean、byte、short、和char类型的数组时,也会转换为使用对应的int类型的字节码指令来处理。因此,大多数对于Boolean、byte、short、和char类型的数据操作,实际上都是使用相应的int类型做为运算类型的(《深入理解Java虚拟机》第二版P198)

自动类型转换

要点:

  • 两种类型是彼此兼容的
  • 转换后的目标类型占的空间范围一定要大于被转化的原类型
  • 数据类型自动提升
    • 如果操作数其中有一个是double类型,两个操作数都转换为double类型
    • 否则,如果其中一个操作数是float类型,两个操作数都转换为loat类型
    • 否则,如果其中一个操作数是long类型,两个操作数都转换为long类型
    • 否则,两个操作数都转换为int类型
public static void main(String[] args) {
		//编译时125,128都是int,编译的时候会检查是否超过byte的范围
		byte a1 = 125;//没有的话,编译器会自动转为byte
		byte a2 = 128;//超过了,编译期间就或报错
		byte b1 = 1;
		byte c1 = 1+1;//表达式中只有常量则会进行常量折叠,等效于byte c1 = 2;
		byte c2 = b1+b1;//计算时转换为int,int赋值给byte报错
		//编译时99999999999999是int,编译的时候会检查是否超过long的范围
		long d1 = 99999999999999; //超过了,则会报错
		//计算时,整数都默认为int,除非加了L后缀表示为long类型
		long d2 = 1000*1000*1000*10;//结果为1410065408:错误,因为超过了int的范围,损失精度,再赋值给long类型时已经是错误的结果了
		long d3 = 1000*1000*1000*10L;//结果为10000000000:正确,因为有个10L,将整个表达式提升为long类型
		long d4 = 1000*1000*1000*10*1L;//结果为1410065408:错误,因为在类型提升之前,计算结果就已超过了int的范围,损失精度,再赋值给long类型时已经是错误的结果了
	}

强制类型转换

显式的强制类型转换遵循以下格式:

TYPE a = (TYPE) B

显式的类型转换大概划分为三种情况:

  1. 高位整型、字符型向低位整型、字符型的强制类型转换

    • 目标类型的长度小于源类型的长度,则在源类型低位直接截取目标类型的长度的数据
  2. 浮点型向整型的强制类型转换

    • 若不超过long或int的最大值,就省略小数部分直接赋值
    • 若超过long或int的最大值,那么强制类型转换的结果就是long或int对应的最大值
    • 浮点型转换为byte/char/short时,需要先以int为跳板,即先转换为int。再按整型的强制类型转换规则,按目标类型长度截取低位数值
  3. 高位浮点型向低位浮点型的强制类型转换

    • double数值在float允许范围之内,float将会直接获取符号位、阶数,并根据浮点数的舍入规则,将double类型52位的尾数舍入为float类型的23位尾数
    • double数值超出float允许范围,这种情况往往是因为阶码部分超出表示范围,尾数只决定精度,阶码才决定范围。若出现这种情况,最后的结果将会输出Infinity或-Infinity,也即正无穷和负无穷。但这并不是数据上的无穷,只是因为浮点数存储机制带来的一种结果

隐式的强制类型转换(只能当两个类型可转时才能进行)

  1. 在赋值表达式中,如果赋值符左右两侧的操作数类型不同,则将赋值符号右操作数强制转换为赋值符号左操作数的类型,然后进行赋值

  2. 在函数调用时,如果return后面的表达式的类型与函数返回值类型不同,则在返回值时将return后的表达式的数值强制转换为函数返回值所定义的类型,再将返回值进行返回

包装类型

基本类型对应的包装类型:

基本数据类型 包装类型
byte Byte
boolean Boolean
short Short
char Character
int Integer
long Long
float Float
double Double

包装类型的应用:

  • 集合类泛型只能是包装类
  • 当需要成员变量不能有默认值时(例如PO)
  • 方法参数允许定义空值时

自动装箱拆箱:

  • 自动装箱即自动将基本数据类型转换成包装类型(java在编译Integer i = 1;的时候,被翻译成->Integer i = Integer.valueOf(1);)
  • 拆箱就是自动将包装器类型转换为基本数据类型
  • 自动装箱拆箱是编译时特性(如果编译时是Integer 需要拆箱,那么运行时传入的参数就必须是Integer )

Java 缓存策略:

Integer的缓存:

Java5为Integer的操作引入了一个新的特性,用来节省内存和提高性能。整型对象在内部实现中通过使用相同的对象引用实现了缓存和重用

  • 默认适用于整数区间 -128 到 +127(这个整数区间可以通过启动应用的虚拟机参数修改:-XX:AutoBoxCacheMax)
  • Integer缓存策略仅在自动装箱(autoboxing)的时候有用
  • 使用构造器创建的Integer对象不能被缓存(构造器方法已被废除,不建议使用)

缓存策略对比较的影响:

  • 无论如何,Integer与new Integer不会相等。不会经历拆箱过程
  • 两个都是非new出来的Integer,如果数在-128到127之间,则是true,否则为false
  • 两个都是new出来的,都为false
  • int和Integer(无论是否new的对象)比,都为true,因为会把Integer自动拆箱为int再去比

Integer的缓存上限可以通过Java虚拟机参数修改,Byte、Short、Long、Character的缓存则没法修改

原文地址:https://www.cnblogs.com/yanghanwen/p/12153840.html