本文目录
- 一、引言
- 二、基本数据类型详解
- 2.1 数值类型
- 2.2 代码示例
- 三、包装类详解
- 3.1 包装类介绍
- 3.2 包装类的主要用途
- 3.3 代码示例
- 四、注意事项和最佳实践
- 4.1 数值计算注意事项
- 4.2 包装类使用建议
- 五、面试重点详解
- 5.1 基本类型和包装类的区别
- 5.2 自动装箱和拆箱的原理
- 5.3 Integer缓存池的实现
- 5.4 浮点数精度问题的解决方案
- 5.5 包装类的equals和==的区别
- 5.6 BigDecimal的使用场景
一、引言
在Java中,数据类型分为两大类:基本数据类型(Primitive Data Types)和引用数据类型(Reference Data Types)。理解这些数据类型的特点和使用场景,对于写出高质量的Java代码至关重要。
二、基本数据类型详解
2.1 数值类型
- 整数类型
- byte:8位,范围-128 ~ 127
- short:16位,范围-32768 ~ 32767
- int:32位,范围-2^31 ~ 2^31-1
- long:64位,范围-2^63 ~ 2^63-1
- 浮点类型
- float:32位,单精度浮点数
- double:64位,双精度浮点数
- 字符类型
- char:16位Unicode字符,范围’\u0000’(0) ~ ‘\uffff’(65535)
- 布尔类型
- boolean:只有true和false两个值
2.2 代码示例
public class PrimitiveTypeDemo {public static void main(String[] args) {// 整数类型示例byte b = 127;short s = 32767;int i = 2147483647;long l = 9223372036854775807L; // 注意使用L后缀// 浮点类型示例float f = 3.14F; // 注意使用F后缀double d = 3.14159265359;// 字符类型示例char c = 'A';char unicode = '\u0041'; // Unicode表示的'A'// 布尔类型示例boolean flag = true;// 打印各类型的值和范围System.out.println("byte value: " + b + ", range: " + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE);System.out.println("short value: " + s + ", range: " + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE);System.out.println("int value: " + i + ", range: " + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE);System.out.println("long value: " + l + ", range: " + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE);System.out.println("float value: " + f);System.out.println("double value: " + d);System.out.println("char value: " + c + ", unicode value: " + unicode);System.out.println("boolean value: " + flag);}
}
三、包装类详解
3.1 包装类介绍
每个基本数据类型都有对应的包装类:
- Byte:byte的包装类
- Short:short的包装类
- Integer:int的包装类
- Long:long的包装类
- Float:float的包装类
- Double:double的包装类
- Character:char的包装类
- Boolean:boolean的包装类
3.2 包装类的主要用途
- 作为对象使用,可以存储在集合中
- 提供了很多实用的方法
- 支持null值
- 用于泛型类型参数
3.3 代码示例
public class WrapperClassDemo {public static void main(String[] args) {// 装箱:基本类型转包装类Integer num1 = Integer.valueOf(10); // 显式装箱Integer num2 = 20; // 自动装箱// 拆箱:包装类转基本类型int num3 = num1.intValue(); // 显式拆箱int num4 = num2; // 自动拆箱// 包装类的常用方法// 1. 字符串转换int i1 = Integer.parseInt("100");double d1 = Double.parseDouble("3.14");// 2. 进制转换String binary = Integer.toBinaryString(10); // 转二进制String hex = Integer.toHexString(10); // 转十六进制String octal = Integer.toOctalString(10); // 转八进制// 3. 常量值System.out.println("Integer MAX_VALUE: " + Integer.MAX_VALUE);System.out.println("Integer MIN_VALUE: " + Integer.MIN_VALUE);// 4. 比较Integer num5 = 127;Integer num6 = 127;Integer num7 = 128;Integer num8 = 128;// 整数缓存池示例(-128 ~ 127)System.out.println("num5 == num6: " + (num5 == num6)); // trueSystem.out.println("num7 == num8: " + (num7 == num8)); // falseSystem.out.println("num7.equals(num8): " + num7.equals(num8)); // true}
}
四、注意事项和最佳实践
4.1 数值计算注意事项
- 浮点数精度问题
public class FloatPrecisionDemo {public static void main(String[] args) {double d1 = 0.1;double d2 = 0.2;System.out.println("0.1 + 0.2 = " + (d1 + d2)); // 0.30000000000000004// 使用BigDecimal处理精确计算BigDecimal bd1 = new BigDecimal("0.1");BigDecimal bd2 = new BigDecimal("0.2");System.out.println("BigDecimal: 0.1 + 0.2 = " + bd1.add(bd2)); // 0.3}
}
4.2 包装类使用建议
- 使用equals()而不是==进行值比较
- 注意Integer缓存池的范围(-128 ~ 127)
- 处理精确计算时使用BigDecimal
- 合理选择基本类型和包装类
五、面试重点详解
5.1 基本类型和包装类的区别
-
存储位置
- 基本类型:存储在栈内存中
- 包装类:存储在堆内存中,栈内存中存储的是引用
-
默认值
- 基本类型:有默认值(如int为0,boolean为false)
- 包装类:默认值为null
-
性能
- 基本类型:运算效率更高
- 包装类:需要额外的内存空间和装箱拆箱操作
public class TypeComparisonDemo {// 类成员变量的默认值示例private int primitiveInt; // 默认值为0private Integer wrapperInt; // 默认值为nullpublic void performanceTest() {// 性能对比long start = System.nanoTime();int sum1 = 0;for(int i = 0; i < 1000000; i++) {sum1 += i;}long primitive = System.nanoTime() - start;start = System.nanoTime();Integer sum2 = 0;for(Integer i = 0; i < 1000000; i++) {sum2 += i; // 涉及装箱拆箱}long wrapper = System.nanoTime() - start;System.out.println("Primitive type time: " + primitive);System.out.println("Wrapper class time: " + wrapper);}
}
5.2 自动装箱和拆箱的原理
-
装箱过程
- 自动装箱是通过调用包装类的valueOf方法实现的
- 例如:Integer i = 10; 实际上是 Integer i = Integer.valueOf(10);
-
拆箱过程
- 自动拆箱是通过调用包装类的xxxValue方法实现的
- 例如:int n = i; 实际上是 int n = i.intValue();
public class AutoBoxingDemo {public static void main(String[] args) {// 自动装箱Integer num1 = 100; // 编译器会转换为: Integer num1 = Integer.valueOf(100);// 自动拆箱int num2 = num1; // 编译器会转换为: int num2 = num1.intValue();// 运算中的自动装箱拆箱Integer num3 = num1 + num2; // 这里涉及到:// 1. num1自动拆箱// 2. 加法运算// 3. 结果自动装箱}
}
5.3 Integer缓存池的实现
-
缓存池范围
- 默认范围:-128 到 127
- 可通过JVM参数调整上限:-XX:AutoBoxCacheMax=
-
实现原理
- Integer类中维护了一个IntegerCache内部类
- 在类加载时初始化缓存数组
- valueOf方法会优先使用缓存池中的对象
public class IntegerCacheDemo {public static void main(String[] args) {// 缓存池范围内Integer num1 = Integer.valueOf(127);Integer num2 = Integer.valueOf(127);System.out.println(num1 == num2); // true// 缓存池范围外Integer num3 = Integer.valueOf(128);Integer num4 = Integer.valueOf(128);System.out.println(num3 == num4); // false// 自动装箱也使用缓存池Integer num5 = 127;Integer num6 = 127;System.out.println(num5 == num6); // true}
}
5.4 浮点数精度问题的解决方案
-
问题原因
- 浮点数采用IEEE 754标准表示
- 二进制无法精确表示某些十进制小数
-
解决方案
- 使用BigDecimal类
- 使用整数运算代替浮点运算
- 使用特定精度的格式化
public class FloatPrecisionDemo {public static void main(String[] args) {// 精度问题示例System.out.println(0.1 + 0.2); // 0.30000000000000004// 解决方案1:使用BigDecimalBigDecimal bd1 = new BigDecimal("0.1");BigDecimal bd2 = new BigDecimal("0.2");System.out.println(bd1.add(bd2)); // 0.3// 解决方案2:使用整数运算System.out.println((1 + 2) / 10.0); // 0.3// 解决方案3:格式化输出DecimalFormat df = new DecimalFormat("#.##");System.out.println(df.format(0.1 + 0.2)); // 0.3}
}
5.5 包装类的equals和==的区别
-
== 运算符
- 比较基本类型:比较值
- 比较引用类型:比较引用(内存地址)
-
equals方法
- 包装类重写了equals方法
- 比较的是值而不是引用
public class EqualsDemo {public static void main(String[] args) {Integer num1 = new Integer(100);Integer num2 = new Integer(100);Integer num3 = 100;Integer num4 = 100;// == 比较System.out.println(num1 == num2); // false(不同对象)System.out.println(num3 == num4); // true(缓存池)// equals比较System.out.println(num1.equals(num2)); // trueSystem.out.println(num3.equals(num4)); // true}
}
5.6 BigDecimal的使用场景
-
主要应用场景
- 金融计算
- 精确的科学计算
- 需要精确小数运算的业务逻辑
-
使用注意事项
- 优先使用String构造器
- 注意scale和舍入模式的设置
- 使用compareTo而不是equals比较值
public class BigDecimalDemo {public static void main(String[] args) {// 创建BigDecimal的正确方式BigDecimal bd1 = new BigDecimal("0.1");BigDecimal bd2 = BigDecimal.valueOf(0.1); // 推荐BigDecimal bd3 = new BigDecimal(0.1); // 不推荐System.out.println("String构造器:" + bd1);System.out.println("valueOf方法:" + bd2);System.out.println("double构造器:" + bd3);// 常见运算BigDecimal price = new BigDecimal("19.99");BigDecimal quantity = new BigDecimal("2");BigDecimal total = price.multiply(quantity);// 设置精度和舍入模式BigDecimal result = total.setScale(2, RoundingMode.HALF_UP);// 比较System.out.println(bd1.compareTo(bd2) == 0); // trueSystem.out.println(bd1.equals(bd2)); // 可能false(scale不同)}
}
今天的内容就到这里了,希望可以对你有帮助。