本文主要是介绍Java中八大包装类举例详解(通俗易懂),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
《Java中八大包装类举例详解(通俗易懂)》:本文主要介绍Java中的包装类,包括它们的作用、特点、用途以及如何进行装箱和拆箱,包装类还提供了许多实用方法,如转换、获取基本类型值、比较和类型检测,...
一、包装类(Wrapper Class)
1、简要介绍
Java 中的包装类是用于将基本数据类型(如 int、char、boolean 等)包装成对象的类。每种基本数据类型都有对应的包装类,这些包装类提供了一种面向对象的方式来处理基本数据类型,允许它们被用于需要对象的场景,如集合框架、泛型等。
以下是 Java 中基本数据类型及其对应的包装类:
基本数据类型 | 对应的包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
2、包装类特点
封装性:所有的包装类都是 final 类,这意味着它们不能被继承。这种设计确保了包装类的行为和特性的一致性,从而避免了子类可能引入的不确定性。
不可变性:包装类的实例一旦被创建后,其中保存的基本数据类型数据就不能再被改变。这种不可变性使得包装类在多线程环境中更加安全,避免了因数据被意外修改而导致的错误。
提供方法:包装类封装了许多实用的方法,提供了丰富的功能。例如,它们支持数据类型转换、判断字符串的大小写、以及获取最大值和最小值等。
继承关系:除了 Characphpter 和 Boolean 之外,其他所有的包装类都继承自 Number 类。这种继承关系使得这些包装类能够共享一些通用的功能和特性,例如数字的比较和转换,这为在不同数值类型之间的操作提供了一致的接口。
3、包装类用途
对象操作:在Java中,许多集合类和框架方法需要对象作为参数,而不是基本数据类型。为了满足这一需求,包装类提供了将基本数据类型转换为对象的机制。通过使用包装类,我们可以轻松地在这些方法中传递基本数据类型。
Null值处理:基本数据类型无法为
null
,而包装类则可以。这一特性在某些情况下非常有用,例如在方法参数中,需要表示可选值或缺省值时。通过使用包装类,我们能够更灵活地处理这些场景,确保代码的健壮性和可读性。这种设计使得我们在处理数据时,可以更方便地进行null
值检查,并在需要时安全地进行区分,从而提高了代码的灵活性。
二、装箱和拆箱
1、装箱和拆箱
装箱(Boxing)是将基本数据类型转换为相应的包装类的过程。拆箱(Unboxing)是将包装类转换为基本数据类型的过程。
手动装箱就是使用一个值创建一个 Integer 对象:
int num = 50000; Integer boxedInt1 = new Integer(num); // 手动装箱方式一 Integer boxedInt2 = Integer.valueOf(num); // 手动装箱方式二
手动拆箱就是使用 Integer 类型对象的 intValue() 方法来获取这个对象的 int 值:
Integer boxedInt = new Integer(5); int num = boxedInt.intValue(); // 手动拆箱
2、自动装箱和自动拆箱
Java 5引入了自动装箱(Auto-boxing)和自动拆箱(Auto-unboxing)机制,简化了基本数据类型与包装类之间的转换过程。
自动装箱是将基本数据类型自动转换为其对应的包装类对象的过程。
int num = 50000; Integer boxedInt = num; // 自动装箱
自动拆箱则是将包装类对象自动转换为其对应的基本数据类型。
Integer boxedInt = new Integer(50000); int num = boxedInt; // 自动拆箱
3、自动装箱和自动拆箱的底层实现
1)自动装箱的底层实现
自动装箱是通过调用包装类的valueOf()方法来实现的。
我们可以通过调试来验证这一结论,在要发生自动装箱的地方打上断点,然后直接跳到这个断点处,然后强制进入(force step into),就会进入到 valueOf() 方法中。
2)自动拆箱的底层实现
自动拆箱是通过调用包装类对象的xxxValue()方法来实现的。
我们可以通过调试来验证这一结论,在要发生自动拆箱的地方打上断点,然后直接跳到这个断点处,然后强制进入(force step into),就会进入到 xxxValue() 方法中。
三、包装类的缓存机制
1、简要介绍
Java中的包装类缓存机制是为了优化性能和节省内存而设计的。
它为整型(Byte、Short、Integer、Long)、字符型(Character)和布尔型(Boolean)的包装类提供了缓存,确保在这些类型的小范围值之间可以复用对象。而对于浮点数类型的包装类(Float、Double),则没有这种缓存机制,意味着每次都需要创建新的对象。
这样一来,Java在处理常用值时更加高效,但在浮点数处理上则相对简单直接。
2、缓存范围
对于 Integer 类,Java会缓存范围在 -128 到 127 之间的所有整数。
对于 Byte、Short 和 Character 类,缓存的范围也是类似的。具体范围如下:
- Byte:-128 到 127
- Short:-128 到 127
- Character:0 到 127(即所有的ASCII字符)
- Boolean:只有 true 和 false 两个值会被缓存。
3、触发缓存机制
只有调用 valueOf() 方法时,如果要创建的值已经被缓存,则会触发缓存机制。
我们可以查看 Integer 类的 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 对php象的值在预定范围内,则返回缓存的对象,如果不在范围内,则直接新创建一个对象。
4、测试缓存机制
我们可以通过使用 valueOf() 方法创建两个值一样且值在范围内的对象,然后比较它们的引用是否相等,如果相等,则能证明缓存机制的存在。
public class Example { pubhttp://www.chinasem.cnlic static void main(String[] args) { Integer i1 = Integer.valueOf(1); Integer i2 = Integer.valueOf(1); System.out.println(i1 == i2); } }
运行结果:
这样就能证明缓存机制的存在。
四、包装类的方法
1、基本转换方法
parseInt(String s), parseDouble(String s), parseBoolean(String s) 等:将字符串转换为相应的基本类型。
valueOf(String s): 返回对应类型的包装类实例,例如 Integer.valueOf("123") 返回一个 Integer 对象。
2、获取基本类型值
intValue(), doubleValue(), charValue(), booleanValue() 等: 返回包装类中封装的基本类型值。
示例:
Integer num = new Integer(5); int value = num.intValue();
3、常量字段
MAX_VALUE, MIN_VALUE: 返回该包装类所表示的基本类型的最大值和最小值。
例如:
Integer.MAX_VALUE 返回 2147483647,
Double.MIN_VALUE 返回 4.9E-324。
4、比较方法
compareTo(T another): 用于比较两个包装类对象的大小。
equals(Object obj): 判断两个对象是否相等。
示例:
Integer.compare(x, y) 方法比较两个 Integer 对象的值。
5、类型检测
isNaN(), isInfinite(): 用于 Double 和 Float 以检测是否为非数字或无穷大。
isLetter(char ch):检查指定的字符是否为字母(包括大写和小写字母)。
char c = 'A'; boolean isLetter = Character.isLetter(c); // 返回 true
isDigit(char ch):检查指定的字符是否为数字。
char c = '5'; boolean isDigit = Character.isDigit(c); // 返回 true
isWhitespace(char ch):检查指定的字符是否为白空格字符(如空格、制表符等)。
char c = ' '; boolean isWhitespace = Character.isWhitespace(c); // 返回 true
五、补充
1、精度提升
public class Example { public static void main(String[] args) { Object obj = true ? new Integer(1) : new Double(2.0); System.out.println(obj); } }
输出结果是:
这是因为由于 Double 精度高,而且这里使用的是三元运算符,所以 Integer 会被提升精度为 Double,所以最终输出的是一个浮点数。
实际上的具体操作应该是:
创建一个 Integer 对象,然后这个对象自动拆箱得到一个 int 类型的值,然后由于后面是 Double 类型,这个 int 类型的值提升为 double 类型的值,然后通过自动装箱得到一个 Double 类型的对象。
我们也可以通过 instanceof 操作符测试一下:
public class Example { public static void main(String[] args) { Object obj = true ? new Integer(1) : new Double(2http://www.chinasem.cn.0); System.out.println(obj instanceof Double); } }
输出结果:
所以说这里的 obj 指向的对象确实是一个 Double 类的对象。
2、包装类与字符串相互转换
1)包装类转换为字符串
Integer i = 10000; // 方式一 String str1 = i + ""; // 方式二 String str2 = i.toString(); // 方式三 String str3 = String.valueOf(i);
这里对于方法三,实际上内部也是调用 toString() 方法的。
2)字符串转换为包装类
String str = "10000"; // 方式一 Integer i1 = Integer.parseInt(str); // 方式二 Integer i2 = Integer.valueOf(str); // 方式三 Integer i3 = new Integer(str);
这里看似通过字符串创建 Integer 类对象有三种方法,实际上就一种方法,对于方法二和方法三内部实际上都是调用js parseInt() 方法来将字符串转换为整型的。
3、缓存机制
上面提到的缓存机制只可能在调用 valueOf() 方法时触发,所以对于直接调用构造方法则不会触发缓存机制。
我们知道自动装箱底层调用的也是 valueOf() 方法,所以说自动装箱也可以触发缓存机制。
我们还知道缓存机制是有范围的,超出范围的值创建的对象都是新创建的。
所以我们就能很自然的得到以下代码的运行结果:
public class Example { public static void main(String[] args) { Integer i1 = new Integer(1); Integer i2 = new Integer(1); System.out.println(i1 == i2); // false Integer i3 = 1; Integer i4 = 1; System.out.println(i3 == i4); // true Integer i5 = 128; Integer i6 = 128; System.out.println(i5 == i6); // false } }
运行结果:
4、判断值是否相等
只要判断中有基本数据类型,则判断的就是值是否相等,也就是说包装类在这时会自动拆箱。
public class Example { public static void main(String[] args) { Integer i1 = 128; int i2 = 128; System.out.println(i1 == i2); } }
运行结果:
总结
到此这篇关于Java中八大包装类的文章就介绍到这了,更多相关Java八大包装类内容请搜索China编程(www.chinasem.cn)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程China编程(www.chinasem.cn)!
这篇关于Java中八大包装类举例详解(通俗易懂)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!