Day3 | Java基础 | 3 Java数据类型
- 基础版
- 数据类型
- 值类型和引用类型的区别
- 数据转换
- 包装类
- BigDecimal
- 常见方法
- 问题回答版
- 基本数据类型
- Java基本数据类型有几种?各占多少位?
- 包装类
- 基础类型和包装类有什么区别?
- 自动装箱与拆箱了解吗?原理是什么?
- Integer
- int和Integer区别是什么?
- Integer缓存机制了解吗?
- BigDecimal
- 为什么浮点数运算时会有精度丢失的风险?
- 怎么避免浮点数精度丢失的问题?
- 如何比较两个BigDecimal是否相等?
基础版
数据类型
Java 中的数据类型有两类:
- 值类型:又叫内置数据类型,基本数据类型
- 引用类型:除值类型以外,都是引用类型,包括String、数组等
值类型和引用类型的区别
- | 基本类型 | 引用类型 |
---|---|---|
概念 | 变量名指向具体的数值 | 变量名指向村数据对象的内存地址 |
内存 | 变量在声明之后,Java会立刻分配给他内存空间 | 以特殊的方式(类似C指针)指向对象实体。这类变量声明时不会分配内存,只是存储了一个内存的地址 |
使用 | 需要赋具体值,判断时使用== | 可以赋null ,判断时使用equals 方法 |
数据转换
自动转换
- 由小数据转换为大数据(扩大转换,不会丢失数据精度)。
这些类型由“小”到“大”分别为:(byte,short,char) < int < long < float < double。
这里我们所说的“大”与“小”,并不是指占用字节的多少,而是指表示值的范围的大小。
- 转换前后的数据类型要兼容
- 整数型和浮点型进行计算后,结果会转为浮点型
强制转换
引用类型也可以使用强制转换。使用括号()
float f = 25.5f;
int x = (int)f;
包装类
以下对象的属性必须使用包装类:
- POJO:Plain Ordinary Java Object,简单无规则的Java对象。只有属性字段、setter和getter方法。
- DTO:Data Transfer Object,数据传输对象。泛指用于展示层与服务层之间的数据传输对象。
- VO:View Object,视图对象。把某个页面的数据封装起来。
- PO:Persistant Object,持久化对象。可以看成是与数据库中的表映射的Java对象。
原因:数据库的查询结果可能是null
,如果使用基本类型的话,因为要自动拆箱(把包装类型转为基本类型,比如把Integer对象转换成int值),就会抛出NullPointException
异常。
BigDecimal
常见方法
创建
使用BigDecimal(String val)
构造方法,或BigDecimal.valueOf(double val)
静态方法,来创建对象
加减乘除
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.add(b));// 1.9 加
System.out.println(a.subtract(b));// 0.1 减
System.out.println(a.multiply(b));// 0.90 乘
System.out.println(a.divide(b));// 无法除尽,抛出 ArithmeticException 异常
System.out.println(a.divide(b, 2, RoundingMode.HALF_UP));// 1.11
其中
public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
return divide(divisor, scale, roundingMode.oldMode);
}
语法含义为
divide(divisor, 保留几位小数, 保留规则(不要选择 UNNECESSARY));
大小比较
BigDecimal a = new BigDecimal("1.0");
BigDecimal b = new BigDecimal("0.9");
System.out.println(a.compareTo(b));// 1 (a>b)
a<b:-1
a=b:0
保留几位小数:setScale()
问题回答版
基本数据类型
Java基本数据类型有几种?各占多少位?
8种。大致分4类(布尔型、字符型、整数型、浮点型)。
基本数据类型 | 分类 | 比特数 | 默认值 | 取值范围 | 说明 |
---|---|---|---|---|---|
boolean | 布尔型 | 8 位 | false | {false,true} | |
char | 字符型 | 16 位 | ‘\u0000’ | [0, 216-1] | 存储Unicode码,用单引号赋值 |
byte | 整数型 | 8 位 | 0 | [-27, 27-1] | |
short | 整数型 | 16 位 | 0 | [-215, 215-1] | |
int | 整数型 | 32 位 | 0 | [-231, 231-1] | |
long | 整数型 | 64 位 | 0L | [-263,263-1] | 赋值时一般在数字后加上l或L |
float | 浮点型 | 32 位 | +0.0f | [2-149, 2128-1] | 赋值时必须在数字后加上f或F |
double | 浮点型 | 64 位 | +0.0D | [2-1074, 21024-1] | 赋值时一般在数字后加d或D |
包装类
基础类型和包装类有什么区别?
参考链接
Java的每个基本类型都对应了一个包装类型。主要区别有四点。
- 包装类型可以为
null
,基本类型不可以。 - 包装类型可用于泛型,基本类型不可以。编译会出错。
List<int> list = new ArrayList<>(); // 提示 Syntax error, insert "Dimensions" to complete ReferenceType
List list = new ArrayList<>();
``
因为泛型在编译时会进行类型擦除,最后只保留原始类型。而原始类型只能是Object类及其子类——基本类型是个特例。
- 基本类型比包装类型更高效。
基本类型在栈中直接存储具体数值,包装类型存储堆中的引用。因此,包装类型需要占用更多的内存空间。假如没有基本类型,对于数值这类经常使用到的数据来说,每次都要通过new一个包装类型就显得非常笨重。
- 两个包装类型的值可以相同,但不相等。
自动装箱与拆箱了解吗?原理是什么?
指基本类型和包装类型之间的转换。
- 装箱boxing:基本类型→包装类型。
- 拆箱unboxing:包装类型→基本类型。
原理:
Java SE5 之前,只能手动:
Integer chenmo = new Integer(10); // 手动装箱
int wanger = chenmo.intValue(); // 手动拆箱
Java SE5 之后,可以自动:
Integer chenmo = 10; // 自动装箱
int wanger = chenmo; // 自动拆箱
上面这段代码使用JAD反编译后的结果:
Integer chenmo = Integer.valueOf(10);
int wanger = chenmo.intValue();
// 也就是说,自动装箱是通过 Integer.valueOf() 完成的;自动拆箱是通过 Integer.intValue() 完成的。
Integer
int和Integer区别是什么?
int是Java的8个原始数据类型之一。Java虽然号称一切都是对象,但原始数据类型是例外。
Integer是int对应的包装类。有一个int类型的字段存储数据,并且提供了基本操作,如数学运算、int和字符串之间转换等。
Integer缓存机制了解吗?
这是Java5中的改进。
构建Integer对象的传统方式是直接调用构造器,直接new一个对象。但实际上,大部分数据操作都集中在有限的、较小的数值范围。所以,Java5中新增静态工厂方法valueOf
,在调用它的时候会利用一个缓存机制,带来了明显的性能改进。这个缓存值得范围默认是-128到127之间。
BigDecimal
参考链接
为什么浮点数运算时会有精度丢失的风险?
与计算机保存浮点数的机制有关。计算机是二进制的,在表示一个数字时,宽度是有限的,无限循环的小数存储在计算机时,只能被截断,从而导致小数精度发生损失。所以浮点数没有办法用二进制精确表示。
浮点数运算
float a = 2.0f - 1.9f;
float b = 1.8f - 1.7f;
System.out.println(a);// 0.100000024
System.out.println(b);// 0.099999905
System.out.println(a == b);// false
怎么避免浮点数精度丢失的问题?
浮点数之间的等值判断,基本数据类型不能用==,包装数据类型不能用equals
可以使用BigDecimal
来进行浮点数运算。
如何比较两个BigDecimal是否相等?
使用compareTo()
方法。
BigDecimal 使用 equals()
方法进行等值比较出现问题的代码示例:
BigDecimal a = new BigDecimal("1");
BigDecimal b = new BigDecimal("1.0");
System.out.println(a.equals(b));//false
这是因为 equals() 方法不仅仅会比较值的大小(value)还会比较精度(scale),而 compareTo() 方法比较的时候会忽略精度。
1.0 的 scale 是 1,1 的 scale 是 0,因此 a.equals(b) 的结果是 false。