Le problème du boxing et du unboxing automatiques est un problème courant en Java. Aujourd'hui, nous allons examiner certains problèmes liés au boxing et au unboxing. Cet article parle d'abord des éléments les plus élémentaires concernant l'emballage et le déballage, puis examine les questions liées à l'emballage et au déballage qui sont souvent rencontrées lors des entretiens écrits.
1. Qu'est-ce que l'emballage ? Qu’est-ce que le déballage ?
Comme mentionné dans l'article précédent, Java fournit des types de wrapper correspondants pour chaque type de données de base. Quant à la raison pour laquelle il fournit des types de wrapper pour chaque type de données de base, je n'entrerai pas dans les détails ici. les amis intéressés peuvent vérifier les informations pertinentes. Avant Java SE5, si vous souhaitez générer un objet Integer d'une valeur de 10, vous devez procéder comme ceci :
Integer i = new Integer(10);
A partir de Java SE5, la fonctionnalité autoboxing est fournie si vous souhaitez générer. un objet Integer avec une valeur de 10, Pour un objet Integer de 10, faites simplement ceci :
Integer i = 10;
Au cours de ce processus, l'objet Integer correspondant sera automatiquement créé en fonction de la valeur, qui est la boxe.
Alors, qu'est-ce que le déballage ? Comme son nom l'indique, correspondant au boxing, cela signifie convertir automatiquement le type de données de base en type de données de base :
Integer i = 10; //装箱 int n = i; //拆箱
Pour faire simple, boxer signifie convertir automatiquement le type de données de base en type de wrapper ; signifie convertir automatiquement le type de wrapper en type de données de base.
Le tableau suivant présente les types de wrapper correspondant aux types de données de base :
2 Comment le boxing et le unboxing sont implémentés
public class Main { public static void main(String[] args) { Integer i = 10; int n = i; } }Après avoir décompilé le class, nous obtenons le contenu suivant : Il ressort du contenu du bytecode obtenu par décompilation que la méthode valueOf(int) de Integer est automatiquement appelée lors de la boxe. Ce qui est automatiquement appelé lors du déballage est la méthode intValue de Integer.
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); System.out.println(i3==i4); } }Peut-être que certains amis diront que le résultat sera faux, ou que certains amis diront que le résultat sera vrai. Mais en fait, le résultat de sortie est :
faux
public static Integer valueOf(int i) { if(i >= -128 && i <= IntegerCache.high) return IntegerCache.cache[i + 128]; else return new Integer(i); }
Et parmi eux, la classe IntegerCache L'implémentation est :
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() {} }Comme le montrent ces deux morceaux de code, lors de la création d'un Integer objet via la méthode valueOf, si la valeur est dans [-128,127] , une référence à un objet qui existe déjà dans IntegerCache.cache est renvoyée, sinon un nouvel objet Integer est créé ;
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); System.out.println(i3==i4); } }Certains amis peuvent penser que le résultat de la question ci-dessus est le même, mais en fait ce n'est pas le cas. Le résultat réel de la sortie est :
false
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); System.out.println(i3==i4); } }La sortie est :
vrai
至于为什么是这个结果,同样地,看了Boolean类的源码也会一目了然。下面是Boolean的valueOf方法的具体实现:
public static Boolean valueOf(boolean b) { return (b ? TRUE : FALSE); }
而其中的 TRUE 和FALSE又是什么呢?在Boolean中定义了2个静态成员属性:
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);
至此,大家应该明白了为何上面输出的结果都是true了。
4.谈谈Integer i = new Integer(xxx)和Integer i =xxx;这两种方式的区别。
当然,这个题目属于比较宽泛类型的。但是要点一定要答上,我总结一下主要有以下这两点区别:
1)第一种方式不会触发自动装箱的过程;而第二种方式会触发;
2)在执行效率和资源占用上的区别。第二种方式的执行效率和资源占用在一般性情况下要优于第一种情况(注意这并不是绝对的)。
5.下面程序的输出结果是什么?
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); System.out.println(e==f); System.out.println(c==(a+b)); System.out.println(c.equals(a+b)); System.out.println(g==(a+b)); System.out.println(g.equals(a+b)); System.out.println(g.equals(a+h)); } }
先别看输出结果,读者自己想一下这段代码的输出结果是什么。这里面需要注意的是:当 “==”运算符的两个操作数都是 包装器类型的引用,则是比较指向的是否是同一个对象,而如果其中有一个操作数是表达式(即包含算术运算)则比较的是数值(即会触发自动拆箱的过程)。另外,对于包装器类型,equals方法并不会进行类型转换。明白了这2点之后,上面的输出结果便一目了然:
true
false
true
true
true
false
true
第一个和第二个输出结果没有什么疑问。第三句由于 a+b包含了算术运算,因此会触发自动拆箱过程(会调用intValue方法),因此它们比较的是数值是否相等。而对于c.equals(a+b)会先触发自动拆箱过程,再触发自动装箱过程,也就是说a+b,会先各自调用intValue方法,得到了加法运算后的数值之后,便调用Integer.valueOf方法,再进行equals比较。同理对于后面的也是这样,不过要注意倒数第二个和最后一个输出的结果(如果数值是int类型的,装箱过程调用的是Integer.valueOf;如果是long类型的,装箱调用的Long.valueOf方法)。
以上所述是小编给大家介绍的Compréhension approfondie du boxing et du unboxing en Java,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网站的支持!
更多Compréhension approfondie du boxing et du unboxing en Java相关文章请关注PHP中文网!