Loading... # 1、包装类 java.lang包中。基本类型数据使用方便,效率高。但是没有对应方法操作它。使用一个类,将基本类型数据包装起来,这个类叫做包装类。包装类中定义了操作基本类型数据的方法。 ## 1.1、基本数据类型对应的包装类型(java.lang包): | int(4字节) | Integer | | ------------------ | ----------- | | byte(1字节) | Byte | | short(2字节) | Short | | long(8字节) | Long | | float(4字节) | Float | | double(8字节) | Double | | char(2字节) | Character | | boolean(1字节) | Boolean | # 2、装箱/拆箱 基本类型与对应的包装类对象之间,来回转换的过程称为“装箱”与“拆箱” * 装箱:从基本类型转换为对应的包装类对象; * 拆箱:从包装类对象转换为对应的基本类型。 基本数值 --> 包装对象 * 构造方法:`Integer i = new Integer(3);` * 静态方法:`Integer i = Integer.valueOf(3);` 包装对象 --> 基本数值 * 成员方法: `int num = i.intValue();` # 3、自动装箱/自动拆箱 * 自动装箱 自动将基本数据类型转换为包装类型。 在JDK1.5之前,如果要生成一个数值为10的Integer对象,必须这样进行: ```java has-numbering Integer i = new Integer(10); ``` 而在从JDK1.5开始就提供了自动装箱的特性,如果要生成一个数值为10的Integer对象,只需要这样就可以了: ```java has-numbering Integer i = 10; ``` 这个过程中会自动根据数值创建对应的 Integer对象,这就是装箱。 * 自动拆箱 自动将包装类型转换为基本数据类型。 ```java has-numbering Integer i = 10; //装箱 int n = i; //拆箱 ``` * 装箱和拆箱的实现 ```java has-numbering public class Main { public static void main(String[] args) { Integer i = 10; // 自动装箱 int n = i; // 自动拆箱 } } ``` 在装箱的时候自动调用的是Integer的valueOf(int)方法。而在拆箱的时候自动调用的是Integer的intValue方法。 装箱过程是通过调用包装类型的valueOf方法实现的,而拆箱过程是通过调用包装器的 xxxValue方法实现的。(xxx代表对应的基本数据类型)。 # 4、基本类型与字符串之间的转换 * 基本类型 --> String 1. 基本数据类型的值 + “”; 2. 包装类的静态方法: `static String toString(int i)` 3. String类的静态方法: `static String valueOf(int i)` * String --> 基本类型:除了Character类之外,其他所有包装类都具有 `parseXxx()` 静态方法可以将字符串参数转换为对应的基本类型 1. `public static byte parseByte(String s)` :将字符串参数转换为对应的byte基本类型。 2. `public static short parseShort(String s)` :将字符串参数转换为对应的short基本类型。 3. `public static int parseInt(String s)` :将字符串参数转换为对应的int基本类型。 4. `public static long parseLong(String s)` :将字符串参数转换为对应的long基本类型。 5. `public static float parseFloat(String s)` 将字符串参数转换为对应的float基本类型。 6. `public static double parseDouble(String s)` :将字符串参数转换为对应的double基本类型。 7. `public static boolean parseBoolean(String s)` :将字符串参数转换为对应的boolean基本类型。 ```java has-numbering public static void main(String[] args) { int i = Integer.parseInt("99"); System.out.println(i); // 注意:如果字符串参数的内容无法正确转换为对应的基本类型,则会抛出 java.lang.NumberFormatException异常。 } ``` # 5、面试相关 ### 5.1、下面这段代码的输出结果是什么? ```java has-numbering public class Main{ public static void main(String[] args) { Integer i1 = 100; Integer i2 = 100; Integer i3 = 200; Integer i4 = 200; System.out.println(i1==i2); // true System.out.println(i3==i4); // false } } ``` 输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。Integer的valueOf方法的具体源码实现: ```java has-numbering public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); } ``` 其中IntegerCache类的实现为: ```java has-numbering private static class IntegerCache { static final int high; static final Integer cache[]; static { final int low = -128; // high value may be configured by property int h = 127; if (integerCacheHighPropValue != null) { // Use Long.decode here to avoid invoking methods that // require Integer's autoboxing cache to be initialized int i = Long.decode(integerCacheHighPropValue).intValue(); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - -low); } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); } private IntegerCache() {} } ``` 从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。 上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。 ### 5.2、下面这段代码的输出结果是什么? ```java has-numbering public class Main { public static void main(String[] args) { Double i1 = 100.0; Double i2 = 100.0; Double i3 = 200.0; Double i4 = 200.0; System.out.println(i1==i2); // false System.out.println(i3==i4); // false } } ``` Double类的valueOf方法会采用与Integer类的valueOf方法不同的实现。很简单:在某个范围内的整型数值的个数是有限的,而浮点数却不是。 【注意】Integer、Short、Byte、Character、Long这几个类的valueOf方法的实现是类似的。 Double、Float的valueOf方法的实现是类似的。 ### 5.3、下面这段代码输出结果是什么? ```java has-numbering public class Main { public static void main(String[] args) { Boolean i1 = false; Boolean i2 = false; Boolean i3 = true; Boolean i4 = true; System.out.println(i1==i2); // true System.out.println(i3==i4); // true } } ``` Boolean的valueOf方法的具体实现: ```java has-numbering public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); } ``` 而其中的 TRUE 和FALSE又是什么呢?在Boolean中定义了2个静态成员属性: ```java has-numbering public static final Boolean TRUE = new Boolean(true); /** * The <code>Boolean</code> object corresponding to the primitive * value <code>false</code>. */ public static final Boolean FALSE = new Boolean(false); ``` ### 5.4、谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。 当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别: 1)第一种方式不会触发自动装箱的过程;而第二种方式会触发; 2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。 ### 5.5、下面程序的输出结果是什么? ```java has-numbering public class Main { public static void main(String[] args) { Integer a = 1; Integer b = 2; Integer c = 3; Integer d = 3; Integer e = 321; Integer f = 321; Long g = 3L; Long h = 2L; System.out.println(c==d); // true System.out.println(e==f); // false System.out.println(c==(a+b)); // true System.out.println(c.equals(a+b)); // true System.out.println(g==(a+b)); // true System.out.println(g.equals(a+b)); // false System.out.println(g.equals(a+h)); // true } } ``` 【注意】 1. 当 "=="运算符的两个操作数都是包装类型的引用,则是比较指向的是否是同一个对象; 2. 而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程); 3. 对于包装器类型,equals方法并不会进行类型转换。 倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。 > 感谢小伙伴们的关注! > 你的点赞、评论、关注、收藏是对博主的最大鼓励! > 持续更新JavaSE学习笔记!欢迎订阅专栏! 最后修改:2021 年 10 月 06 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 如果觉得我的文章对你有用,请随意赞赏