java se 类库_19、【JavaSE】【Java 核心类库(上)】包装类

1、概念

通常情况下基本数据类型的变量不是对象(基本数据类型的数据一般是在栈中的),为了满足万物皆对象的理念就需要对基本数据类型的变量进行打包封装处理变成对象,而负责将这些变量声明为成员变量进行对象化处理的相关类,叫做包装类。

包装类所做的实际上就是一种封装。

public class Integer {

// 封装

private int num;

······

}

2、Java 中的包装类与对应的数据类型

d9d0dd8ad169

包装类与其对应的基本数据类型

3、java.lang.Integer

java.lang.Integer类内部包装了一个int类型的变量作为成员变量,主要用于实现对int类型的包装并提供int类型到String类之间的转换等方法。

public final class Integer extends Number implements Comparable {

······

private final int value;

······

}

java.lang.Integer中常用的常量与方法:

d9d0dd8ad169

Integer 类

“装箱”(Boxing)与“拆箱”(Unboxing):

将基本数据类型转换为包装类的过程称为“装箱”;将包装类转换为基本数据类型称为“拆箱”。

在 Java 5 之前,“装箱”与“拆箱”是必须要借助方法完成的,例如说:int转Integer需要借助java.lang.Integer的构造方法或者是valueOf方法,Integer转int必须借助intValue方法。

在 Java 5 之后,支持“自动装箱”、“自动拆箱”。

public class IntegerTest {

public static void main(String[] args) {

// 自动“装箱”

Integer x = 100;

// 自动“拆箱”

int y = x + 200;

}

}

包装类的==和equals,==仍是比较引用所指向的对象(内存空间)是否是同一个,equals被重写后来比较值是否相等。对于java.lang.Integer来说,还是有些特殊的地方需要注意的。

d9d0dd8ad169

Integer 类==特殊性

public class IntegerTest {

public static void main(String[] args) {

Integer x = 1000;

Integer y = 1000;

System.out.println(x == y); // false 比较引用指向对象是否是同一个,即比较地址

System.out.println(x.equals(y)); // true 比较值是否相等

}

}

public class IntegerTest {

public static void main(String[] args) {

Integer x = 127;

Integer y = 127;

System.out.println(x == y); // true 从缓存中直接取,两个引用指向的都是同一个对象

System.out.println(x.equals(y)); // true 比较值是否相等

}

}

d9d0dd8ad169

Integer 类使用建议

// Integer -128~127 “自动装箱池” 源码

private static class IntegerCache {

static final int low = -128;

static final int high;

static final Integer cache[];

static {

// high value may be configured by property

int h = 127;

String integerCacheHighPropValue =

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;

}

private IntegerCache() {}

}

补充说明:这个范围(-128~127)是可以调整的,将会涉及到 JVM 优化。

java.lang.Number是一个抽象类,所有数值的包装类都继承了该抽象类。

d9d0dd8ad169

继承 Number 类的包装类

4、java.lang.Boolean

java.lang.Boolean类型内部包装了一个boolean类型的变量作为成员变量,主要用于实现对boolean类型的包装并提供boolean类型到String类之间的转换等方法。

java.lang.Boolean中常用的常量与方法:

d9d0dd8ad169

Boolean 类

java.lang.Boolean源码需要注意的:

// parseBoolean 源码

public static boolean parseBoolean(String s) {

return "true".equalsIgnoreCase(s);

}

// equals 源码

public boolean equals(Object obj) {

if (obj instanceof Boolean) {

return value == ((Boolean)obj).booleanValue();

}

return false;

}

// valueOf 源码

public static Boolean valueOf(boolean b) {

return (b ? TRUE : FALSE);

}

从java.lang.Boolean的源码可以看出,java.lang.Boolean的设计理念有些类似于枚举,其中TRUE和FALSE就相当于枚举量。无论我们有多少个Boolean的引用,在堆上也就只有两个Boolean对象,一个对象是包装了true,另一个对象是包装了false。

d9d0dd8ad169

Boolean 类的设计理念

通过上面的图,也就能解释下面代码的输出了:

public class BooleanTest {

public static void main(String[] args) {

Boolean b1 = true;

Boolean b2 = true;

System.out.println(b1 == b2); // true

System.out.println(b1.equals(b2)); // true

}

}

5、java.lang.Character

java.lang.Character类型内部包装了一个char类型的变量作为成员变量,主要用于实现对char类型的包装并提供字符类别的判断和转换等方法。

java.lang.Character中常用的常量与方法:

d9d0dd8ad169

Character 类

在java.lang.Character中同样存在类似于java.lang.Integer中-128~127范围,java.lang.Character的范围是0~127,也就是 ASCII 码表中的字符都是在自动装箱池(也叫“缓存”)中的。

public class CharacterTest {

public static void main(String[] args) {

Character c1 = 'a';

Character c2 = 'a';

System.out.println(c1 == c2); // true

System.out.println(c1.equals(c2)); // true

}

}

6、总结

d9d0dd8ad169

包装类

7、勘误与补充

在本篇文章中所叙述的包装类的缓存机制在涉及到具体实现以及底层分析的时候在语言表述上会有一定的偏差,但是也是勉强可以接受的。

虽然包装类中的构造方法被标注过时,但是,仍有些情况要稍微关注一下:

public class IntegerTest {

public static void main(String[] args) {

Integer x = new Integer(16);

Integer y = new Integer(16);

System.out.println(x == y); // false 也就是说如果使用的是 new 来创建包装类对象,是不会考虑缓存机制的。自动装箱或者 valueOf 方法是考虑缓存机制的

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值