包装类
Java中的数据类型有三种:
-
字符类型
char 16位,存储Unicode码,用单引号赋值
-
布尔类型
Boolean 只有true和false两个取值
-
数值类型
3.1 byte 8位,最大存储数据量是255,存放的数据范围是-128~127之间
3.2 short 16位,最大数据存储量是65536,数据范围是-32768~32767之间
3.3 int 32位,最大数据存储容量是2的32次方减1,数据范围是负的2的31次方到正的2的31次方减1
3.4 long 64位,最大数据存储容量是2的64次方减1,数据范围为负的2的63次方到正的2的63次方减1
3.5 float 32位,数据范围在3.4e-45~1.4e38,直接赋值时必须在数字后加上f或F
3.6 double 64位,数据范围在4.9e-324~1.8e308,赋值时可以加d或D也可以不加
在Java中,程序运行时有一个栈和堆,引用类型的数据都保存在堆中,基本类型的数据存储在栈中,栈中同时也保存引用类型在堆中的地址。
由于基本数据类型没有对应的函数可以调用,只能通过简单的运算符号来进行操作,故这里可以提供一些对应的类来为这些基本数据类型提供更方便的操作。这些类也被称为包装类。故包装类就是基本数据类型所对应的引用数据类型。
Object类可以统一所有数据,包装类的默认值是null。
包装类的对应关系如下表所示。
基本数据类型 | 包装类型 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
类型转换与装箱、拆箱
根据前面知道的,引用类型的数据存放在堆中,基本类型的数据存储在栈中,对于一个基本数据类型来说,存放在栈中,那么如果想将栈中的数据拿到堆中,借助对应的包装类(转换为引用类型),这个过程被称为装箱;如果要把堆中的对象拿到栈中,也就是转换为基本数据类型,这个过程被称为拆箱。
接下来以Integer类为例,展示其中的一些类函数。
装箱与拆箱的示例代码如下所示。
package PackingClass;
public class demo01 {
public static void main(String[] args) {
int num = 10;
/*
* JDK 1.5之前的装箱拆箱操作
* */
// 类型转换:装箱,基本类型 转成 引用类型
int num1 = 18; // 基本类型的数据
// 使用Integer类进行包装
Integer integer1 = new Integer("123");
Integer integer2 = new Integer(1234);
Integer integer3 = Integer.valueOf(12345);
// 类型转换:拆箱,引用类型 转成 基本类型
Integer integer4 = new Integer(100);
int num2 = integer4.intValue();
System.out.println(num2);
/*
* JDK 1.5之后提供自动装箱和拆箱的功能
* */
int age = 30;
// 自动装箱
Integer integer = age;
// 自动拆箱
int age2 = integer;
System.out.println(age2);
}
}
基本类型与字符串的转换
将基本类型转换成字符串时,可以使用简单的+来进行转换,也可以使用包装类中的toString函数来进行实现,同时也包含其他的一些函数,如下所示。
将字符串转换成数字的时候,也可以使用包装类中的函数来进行实现。
需要注意的是boolean类型,boolean字符串类型转成基本类型,“true”—> true, 非"true"—>false。示例代码如下所示。
package PackingClass;
public class demo02 {
public static void main(String[] args) {
// 基本类型与字符串之间转换
// 1. 基本类型转成字符串
int n1 = 100;
// 1.1 使用 + 号
String s1 = n1 + "";
System.out.println(s1);
// 1.2 使用Integer中的toString()方法
String s2 = Integer.toString(n1, 8); // 将n1转成8进制,然后转成字符串
System.out.println(s2);
// 2 字符串转换成基本类型
String str = "150";
// 使用Integer.parseXXX()
int n2 = Integer.parseInt(str);
System.out.println(n2);
// boolean字符串类型转成基本类型,"true"---> true, 非"true"--->false
String str2 = "trua";
boolean b1 = Boolean.parseBoolean(str2);
System.out.println(b1);
}
}
注意:需要保证类型兼容,否则抛出NumberFormatException异常。
整数缓冲区
在Integer类中,自动装箱其实调用的是valueOf函数,接下来查看啊valueOf函数源码:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
从上述源码中可以看出,Integer类中有一个IntegerCache缓冲区,同时查看源码知道low为-128,high为127。在静态代码块中创建了-128到127的Integer对象,静态代码块如下所示。
static {
// high value may be configured by property
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
再次结合valueOf函数的实现,如果要创建-128~127之间的Integer对象,则直接返回Integer缓冲区中已经创建好的对象,反之才会重新创建新的对象。
故Java预先创建了256个常用的整数包装类型对象,在实际应用当中,对已创建的对象进行复用即可,减少内存的消耗。
测试代码:
package PackingClass;
public class demo03 {
public static void main(String[] args) {
// 面试题、
Integer integer1 = new Integer(100);
Integer integer2 = new Integer(100);
// 地址不同,故会返回false
System.out.println(integer1 == integer2);
Integer integer3 = 100; // 自动装箱
Integer integer4 = 100; // 自动装箱
System.out.println(integer3 == integer4);
Integer integer5 = 200;
Integer integer6 = 200;
System.out.println(integer5 == integer6);
Integer integer7 = -128; // 自动装箱
Integer integer8 = -128; // 自动装箱
System.out.println(integer7 == integer8);
}
}