一、为什么需要包装类;
JAVA虽然号称一切都是对象,所有类型都是引用类型。并且所有类都是继承自Object,并且是不需要进行指定明确继承的类。但不过JAVA的基本数据类型却是例外。不是对象也不继承自Object,因此JAVA需要包装类来保证面向对象的完整性,并且包装类同时也可以实现空类型,JAVA集合中也只能放入包装类。二、有哪些包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
三、包装类与自动装箱拆箱
3.1:什么是自动装箱拆箱
在JAVA 5中,引入了自动装箱和自动拆箱功能,JAVA可以根据上下文,自动进行转换,极大地简化了相关编程。装箱:将基本类型转换成对应的包装类型
拆箱:将包装类型转换成对应的基本类型
3.2如何进行装箱拆箱的
自动装箱比如:Integer i = 100;
相当于编译器进行:
Integer i =Integer.valueOf(100);
源码:
1 public static Integer valueOf(int i) {
2 return i >= 128 || i < -128 ? new Integer(i) : SMALL_VALUES[i + 128];
3 }
源码分析:
从源码可以看出,如果数值在129和-128之间则返回SMALL_VALUES数组中的引用值!
自动拆箱
比如
Integer i =100;int x = i;
int x = Integer.intValue();
源码:
1 @Override
2 public int intValue() {
3 return value;
4 }
可以发现其是直接返回value的值
3.2:包装类与普通类进行比较!
看下面例子 Integer a = 1;
Integer b = 2;
Integer c = 3;
Integer d = 3;
Integer e = 150;
Integer f = 150;
Long g = 3L;
System.out.println(c==d);//true 1
System.out.println(e==f);//false 2
System.out.println(c==(a+b));//true 3
System.out.println(g==(a+b));//true 4
System.out.println(c.equals(a+b));//true 5
System.out.println(g.equals(a+b));//false 6不是同一类型
System.out.println(g.equals((long)(a+b)));//true 7首先比较是不是同一类型,再比较值
- 分析1,2:1为什么为true,2为什么为false呢?
首先作为对象直接使用==进行比较,比较的是其内存地址。从其输出结果为true来看,说明其内存地址相同。那么为什么1的内存地址相同,而2为false勒?这里我们使用Integer进行举例
从上面我们知道包装类进行自动装箱时,是调用了Integer.valueOf函数,从源码可知:因为c,d为3属于Integer缓存数组范围内,因此c,d为同一对象,所以其内存地址相同,而e,f为150大于缓存范围,所以就不是同一对象,故不相同 - 分析3,4:原因是在==运算的时候,如果两端中任何一端含有算术表达式,就会发发生自动解包,这时比较的是值
- 分析5,6,7:equals可以比较对象的值,因此5为true,推荐使用,但前提是相同的对象类型!如果是不同类型勒,那么就是6则为false,但可以使用强制类型转换如7则为true
3.3:3.2的补充
首先看一下Integer进行缓冲的数组;
1 private static final Integer[] SMALL_VALUES = new Integer[256];
1.它是一个静态的Integer数组对象,也就是说如果在范围内,那么最终valueOf返回的都是同一个Integer对象。(不是缓存范围内的值)这里我们可以总结一点:装箱的过程会创建对应的对象,这个会消耗内存,所以装箱的过程会增加内存的消耗会影响性能。
2.如果对于特别的应用场景,如果会更频繁使用更大的数值,这时候缓存上限值实际是可以根据需要调整的,JVM提供了参数设置:-xx:AutoBoxCacheMax=N;看源码
private satic class IntegerCache {
satic fnal int low = -128;
satic fnal int high;
satic fnal Integer cache[];
satic {
// high value may be confgured by property
int h = 127;
String integerCacheHighPropValue = VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
...
// range [-128, 127] mus be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
...
}
3:大家基本上都知道字符串的是不可变的,但是其实包装类里存储数值的成员变量value,其变量声明为“private final”,因此其同样也是不可变的
4.总结
- 为什么需要包装类
- 基本数据类型以及其对应的包装类
- 包装类与基本数据类型如何进行比较,如何进行装包解包及其源码分析
- 其他知识