数据类型
- Java的数据类型分为:基本类型、引用类型。
- String是引用类型,是lang包下的类。
1、基本数据类型
- Java 中有 8 种基本数据类型。
4 种整数型:byte、short、int、long
2 种浮点型:float、double
1 种字符类型:char
1 种布尔型:boolean
- Java数据类型所占存储空间大小与机器硬件结构无关,可移植性更高。
基本数据类型 | 字节数 | 包装类 | |
---|---|---|---|
布尔型 | boolean | 1 | Boolean |
字符型 | char | 2 | Character |
整型 | byte | 1 | Byte |
整型 | short | 2 | Short |
整型 | int | 4 | Integer |
整型 | long | 8 | Long |
浮点型 | float | 4 | Float |
浮点型 | double | 8 | Double |
2、包装类
- 包装类将基本数据类型包装转化为类的形式,具有面向对象的特征。
- Java集合中只能放入包装类型,而不支持基本类型。
- Java类型间的转换可以通过包装类的方法实现,基本数据类型没有类的属性方法。
- 所有整型包装类对象之间值的比较,全部使用 equals 方法比较。
对于 Integer var 在-128 至 127 之间的赋值,Integer 对象是在 IntegerCache.cache 产生, 会复用已有对象,这个区间内的Integer 值可以直接使用==进行判断.
但是这个区间之外的所有数据,都会在堆上产生,并不会复用已有对象,使用 equals 方法进行判断。
3、基本类型和包装类型的区别
- 默认值:包装类型不赋值就是 null ,基本类型有默认值且不是 null。
- 包装类型可用于泛型,而基本类型不可以。
- 包装类型属于对象类型,几乎所有对象实例都存在于堆中。
- 基本数据类型的局部变量存放在 Java 虚拟机栈中的局部变量表中。
- 基本数据类型的成员变量(未被 static 修饰 )存放在 Java 虚拟机的堆中。
4、包装类型的缓存机制
- 包装类型的大部分都用到了缓存机制来提升性能:节省创建对象的时间开销。对象可以自由共享。
- Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据。
- Character 创建了数值在 [0,127] 范围的缓存数据。
- Boolean 直接返回 True or False。
- Float,Double 并没有实现缓存机制。
- 如果超出对应范围会创建新的对象,缓存的范围区间的大小只是在性能和资源之间的权衡。
- 包装器类提供了对象的缓存,String类提供了常量池,都有final修饰,对象一经创建后不可修改。
5、equals() 和 ==
==
- 对于基本数据类型来说,== 比较的是值。
- 对于引用数据类型来说,== 比较的是对象的内存地址。
- == 运行速度比equals()快,因为==只是比较引用。
equals()
- equals() 不能用于判断基本数据类型的变量,只能用来判断两个对象是否相等。
- equals()方法存在于Object类中,而Object类是所有类的直接或间接父类,因此所有的类都有equals()方法。
- 如果类没有重写 equals()方法:等价于通过“==”比较这两个对象,使用的默认是 Object类equals()方法。是否为同一内存地址。
- 如果类重写了 equals()方法 :一般会重写 equals()方法来比较两个对象中的属性是否相等;若它们的属性相等,则返回 true(即,认为这两个对象相等)。
- String 中的 equals 方法是被重写过的,比较的是对象的值。
当创建 String 类型的对象时,虚拟机会在常量池中查找有没有已经存在的值和要创建的值相同的对象,如果有就把它赋给当前引用。如果没有就在常量池中重新创建一个 String 对象。
String a = new String("ab"); // a 为一个引用
String b = new String("ab"); // b为另一个引用,对象的内容一样
String aa = "ab"; // 放在常量池中
String bb = "ab"; // 从常量池中查找
System.out.println(aa == bb);// true
System.out.println(a == b);// false
System.out.println(a.equals(b));// true
System.out.println(42 == 42.0);// true
6、自动装箱拆箱
- 装箱:将基本类型用它们对应的引用类型包装起来;调用了包装类的valueOf()方法。
- 拆箱:将包装类型转换为基本数据类型;调用了 intValue()方法。
- 如果频繁拆装箱的话,也会严重影响系统的性能。应该尽量避免不必要的拆装箱操作。
public static void WrapTest1() {
// 自动装箱,等效于 Integer num = Integer.valueOf(100);
Integer num = 100;
// 自动拆箱,等效于 int num2 = num.intValue();
int num2 = num;
// valueOf() 方法返回对应包装类实例
System.out.println("-----valueOf()-----");
Integer a =Integer.valueOf(9); // 将int转为Integer包装类对象
Double b = Double.valueOf(5);
Float c = Float.valueOf("80"); // 将字符串转为Float包装类对象
Integer d = Integer.valueOf("444",16); // 使用 16 进制
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
结果:
-----valueOf()-----
9
5.0
80.0
1092
7、浮点数精度丢失
- 浮点数运算的时候会有精度丢失的风险。计算机使用有限的宽度表示一个数字,无限循环的小数存储在计算机时,只能被截断。
- BigDecimal 可以实现对浮点数的运算,不会造成精度丢失。
- BigInteger 内部使用 int[] 数组来存储任意大小的整形数据。
8、代码
// 大小与范围
public static void WrapTest0() {
// byte
System.out.println("基本类型:byte 二进制位数:" + Byte.SIZE);
System.out.println("包装类:java.lang.Byte");
System.out.println("最小值:Byte.MIN_VALUE=" + Byte.MIN_VALUE);
System.out.println("最大值:Byte.MAX_VALUE=" + Byte.MAX_VALUE);
System.out.println();
// char 单一的 16 位 Unicode 字符;
System.out.println("基本类型:char 二进制位数:" + Character.SIZE);
System.out.println("包装类:java.lang.Character");
// 以数值形式而不是字符形式将Character.MIN_VALUE输出到控制台 \u0000(十进制等效值为 0);
System.out.println("最小值:Character.MIN_VALUE=" + (int) Character.MIN_VALUE);
// 以数值形式而不是字符形式将Character.MAX_VALUE输出到控制台 \uffff(即为 65535);
System.out.println("最大值:Character.MAX_VALUE=" + (int) Character.MAX_VALUE);
}
结果:
基本类型:byte 二进制位数:8
包装类:java.lang.Byte
最小值:Byte.MIN_VALUE=-128
最大值:Byte.MAX_VALUE=127
基本类型:char 二进制位数:16
包装类:java.lang.Character
最小值:Character.MIN_VALUE=0
最大值:Character.MAX_VALUE=65535
public static void WrapTest2() {
System.out.println("-----缓存池范围-----");
Integer a = 100, b = 100;
System.out.println(a == b); //true // 比较引用地址相同,缓存池中为同一对象
System.out.println(a.equals(b)); //true // 比较对象内容相等
Long c = 145L, d = 145L;
System.out.println(c == d); //false // 比较引用地址不同,超出缓存池范围重新new了不同对象
System.out.println(c.equals(d)); //true // 比较对象内容相等
System.out.println(c.intValue() == d.intValue()); // true
System.out.println("-----不同包装类对象-----");
Integer i = 130;
Long j = 130L;
System.out.println(i.equals(j)); //false // equals()会先判断包装类型,若j是不同类型,直接false
// 不同包装类对象不能用==比较
System.out.println("-----不同基本数据类型-----");
int m = 100;
long n = 100L;
System.out.println(m == n); //true // 基本数据类型没有缓存池的概念,用 == 比较
int M = 150;
long N = 150L;
double O = 150.0;
System.out.println(M == N); //true // 基本数据类型 ==比较,都指向相同堆地址
System.out.println(M == O); //true
System.out.println("-----包装类和基本数据类型-----");
Long x = 145L;
long y = 145l;
System.out.println(x == y); //true // == 会自动拆箱
System.out.println(x.equals(y)); //true // 自动装箱
int z = 145;
System.out.println(x == z); //true // == 会自动拆箱x 为long
System.out.println(x.equals(z)); //false // equals()自动装箱z 为Integer, 不同包装类对象用equals()比较直接false
Integer i1 = 40; // 缓存中的对象
Integer i2 = new Integer(40); // 创建新的对象
System.out.println(i1==i2); // false
}
// 基本数据类型与字符串的转换
public static void WrapTest3() {
// 基本数据类型转换为String
String str1 = String.valueOf(111);
String str2 = 222 + "";
String str3 = Integer.toString(333);
// 字符串转换成基本数据类型
int a = Integer.parseInt("111");
// 字符串转换成包装类
Integer b = Integer.valueOf("222");
// 包装类型转换为字符串类型
String str4 = String.valueOf(Integer.valueOf(444));
}
public static void intTest() {
System.out.println(5/2);
double x = 1.0 / 10;
double y = 1 - 9.0 / 10;
System.out.println(x);
System.out.println(y);
// 四舍五入
double d = 2.6;
int n = (int) (d + 0.5);
System.out.println(n);
double e = 2.4;
int m = (int) (e + 0.5);
System.out.println(m);
char c3 = '\u0041';
System.out.println(c3);
double d = 12900000;
System.out.println(d);
double e = 3.1415926;
System.out.printf("%.2f\n", e);
System.out.printf("%.4f\n", e);
int n = 12345000;
System.out.printf("n=%d, hex=%08x \n", n, n);
System.out.printf("%%%d", n);
}
参考
https://tobebetterjavaer.com/basic-grammar/basic-data-type.html#%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B%E7%9A%84%E5%88%86%E7%B1%BB
https://javaguide.cn/java/basis/java-basic-questions-01.html#%E8%87%AA%E5%8A%A8%E8%A3%85%E7%AE%B1%E4%B8%8E%E6%8B%86%E7%AE%B1%E4%BA%86%E8%A7%A3%E5%90%97-%E5%8E%9F%E7%90%86%E6%98%AF%E4%BB%80%E4%B9%88