Java核心类(2 - 包装类型)
包装类型
Java的数据类型分为两种:
- 基本数据类型:
byte
,char
,short
,int
,long
,boolean
,float
,double
- 引用类型:所有的
class
和interface
类型
Java核心库为每种基本类型都提供了对应的包装类型:
基本类型 | 引用类型 |
---|---|
boolean | java.lang.Boolean |
byte | java.lang.Byte |
short | java.lang.Short |
int | java.lang.Integer |
long | java.lang.Long |
double | java.lang.Double |
char | java.lang.Char |
float | java.lang.Float |
自动装箱(Auto Boxing)和自动拆箱(Auto Unboxing)
因为int
和Integer
可以相互转换:
int num = 99;
Integer Num = Integer.valueOf(num);
int n = Num.intValue();
所以,Java编译器可以帮助我们自动在int
和Integer
之间转换:
Integer a = 100; // 编译器自动使用Integer.valueOf(int)
int b = a; // 编译器自动使用Integer.intValue()
这种把int
变为Integer
的赋值写法,称为自动装箱,反之,把Integer
变为int
的赋值写法,称为自动拆箱。
注意: 自动装箱和自动拆箱只发生在编译阶段,目的是少写代码。
不变类
所有包装类型都是不变类。我们查看Integer
的源码可知,它的核心代码如下:
public final class Integer{
private final int value;
}
因此,一旦创建Integer
对象,该对象是不可变的。
对两个Integer
对象进行比较时,不要使用==
进行比较,一定要使用equals()
方法进行比较,因为Integer
是引用类型。
public class Main {
public static void main(String[] args) {
Integer a = 127 ;
Integer b = 127 ;
System.out.println(a==b);
Integer c = 128;
Integer d = 128 ;
System.out.println(c==d);
Integer x = 1000;
Integer y = 1000;
System.out.println(x==y);
Integer m = new Integer(100);
Integer n = new Integer(100);
System.out.println(m==n);
}
}
输出:
true
false
false
false
为什么a=b呢?原因很简单,因为在Integer
类中,事先开辟了一个大小为256的Integer
数组SMALL_VALUES,用于存[-127,128]这固定的256个值,目的是为了避免多次创建对象。如果创建的对象的值在这个范围内,就可以直接返回我们事先创建好的对象。
i>=128 || i<-128 => new Integer(i)
i<=127 && i>=-128 => SMALL_VALUES[i+128]
在整型数据我们可以这么做,但是对于浮点数(Double
和Float
)来说,我们不能这么做,因为在这个范围内的浮点数是无限的。
综述:在某个范围内的整型数值的个数是无限的,而浮点数不是。
类型 | 相同对象范围 | 不同对象范围 |
---|---|---|
Integer | [-128,127] | i>=128 || i<-128 |
Short | [-128,127] | s>=128 || s<-128 |
Character | [0,127] | c>=128 |
Long | [-128,127] | v>=128 || v<-128 |
对于new出来的相同数值的包装类,不论大小,用==
比较结果一定是false
进制转换
Integer
类本身还提供了大量方法。例如,最常用的静态方法parseInt()
可以把字符串解析成一个整数:
public class Main {
public static void main(String[] args) {
int a= Integer.parseInt("100",2); // 4 把100看成二进制数
System.out.println(a);
int b= Integer.parseInt("100",8); // 64 把100看成八进制数
System.out.println(b);
int c= Integer.parseInt("100",16); // 256 把100看成十六进制数
System.out.println(c);
}
}
输出:
4
64
256
Integer
类还可以把整数格式化为指定进制的字符串:
public class Main {
public static void main(String[] args) {
System.out.println(Integer.toString(100)); // "100",表示为十进制
System.out.println(Integer.toString(100,16)); // "64",表示为十六进制
System.out.println(Integer.toString(100,36)); // "2s",表示为36进制
System.out.println(Integer.toBinaryString(100)); // "1100100",表示为2进制
System.out.println(Integer.toOctalString(100)); // "144",表示为八进制
System.out.println(Integer.toHexString(100)); // "64",表示为十六进制
}
}
输出:
100
64
2s
1100100
144
64
程序设计的一个重要原则:数据的存储和显示要分离
。
Java的包装类型还定义了一些有用的静态常量:
public class Main {
public static void main(String[] args) {
Boolean a = Boolean.TRUE;
Boolean b = Boolean.FALSE;
System.out.println(a); // true
System.out.println(b); //false
int max = Integer.MAX_VALUE;
int min = Integer.MIN_VALUE;
System.out.println(max); // 2147483647
System.out.println(min); // -2147483648
int sizeOfLong = Long.SIZE;
int bytesOfLong = Long.BYTES;
System.out.println(sizeOfLong); //64(bits)
System.out.println(bytesOfLong); //6(bytes)
}
}
输出:
true
false
2147483647
-2147483648
64
8
最后,所有的整数和浮点数的包装类型都继承自Number
,因此,可以非常方便的直接通过包装类型获取各种基本类型:
Number n = Integer.valueOf(1000);
byte a = n.byteValue();
double b = n.doubleValue();
int c = n.intValue();
long d = n.longValue();
float e = n.floatValue();
处理无符号整型
在Java中,并没有无符号整型(Unsigned)的基本数据类型,byte
、short
、int
和long
都是带符号整型,最高位是符号位。无符号整型和有符号整型的转换在Java中就需要借助包装类型的静态方法完成。
public class Main {
public static void main(String[] args) {
byte a = -1;
System.out.println(Byte.toUnsignedInt(a));
byte b = 127;
System.out.println(Byte.toUnsignedInt(b));
}
}
输出:
255
127
-1
的二进制为11111111
,以无符号整型转换后的int
就是255
。