Heim  >  Artikel  >  Java  >  Vertiefte Kenntnisse des Boxens und Unboxings in Java

Vertiefte Kenntnisse des Boxens und Unboxings in Java

高洛峰
高洛峰Original
2017-01-24 14:03:451429Durchsuche

Das Problem des automatischen Ein- und Auspackens ist in Java ein alltägliches Problem. Heute werfen wir einen Blick auf einige Probleme beim Ein- und Auspacken. In diesem Artikel geht es zunächst um die grundlegendsten Dinge rund um das Ein- und Auspacken und dann um die Fragen zum Ein- und Auspacken, die in schriftlichen Vorstellungsgesprächen häufig gestellt werden.

1. Was ist eine Verpackung? Was ist Unboxing?

Wie im vorherigen Artikel erwähnt, stellt Java für jeden Basisdatentyp entsprechende Wrappertypen bereit. Ich werde hier nicht näher darauf eingehen. Interessierte Freunde können relevante Informationen überprüfen. Wenn Sie vor Java SE5 ein Integer-Objekt mit dem Wert 10 generieren möchten, müssen Sie wie folgt vorgehen:

Integer i = new Integer(10);

Ab Java SE5 steht Ihnen die Autoboxing-Funktion zur Verfügung ein Integer-Objekt mit einem Wert von 10. Für ein Integer-Objekt von 10 gehen Sie einfach wie folgt vor:

Integer i = 10;

In diesem Prozess wird das entsprechende Integer-Objekt automatisch basierend auf dem Wert erstellt, der eingerahmt ist.

Was ist also Auspacken? Wie der Name schon sagt, bedeutet Boxen die automatische Konvertierung des Wrapper-Typs in den Basisdatentyp:

Integer i = 10; //装箱
int n = i; //拆箱

Vereinfacht ausgedrückt bedeutet Boxen die automatische Konvertierung des Basisdatentyps in den Unboxing-Typ bedeutet, dass der Wrapper-Typ automatisch in den Basisdatentyp konvertiert wird.

Die folgende Tabelle zeigt die Wrapper-Typen, die den grundlegenden Datentypen entsprechen:

Vertiefte Kenntnisse des Boxens und Unboxings in Java

2. Wie Boxing und Unboxing implementiert werden

Nachdem wir im vorherigen Abschnitt die grundlegenden Konzepte des Boxens verstanden haben, lernen wir in diesem Abschnitt, wie Boxen und Unboxing implementiert werden.

Nehmen wir die Interger-Klasse als Beispiel:

public class Main {
public static void main(String[] args) {
Integer i = 10;
int n = i;
}
}

Nach dem Dekompilieren In der Klassendatei erhalten wir den folgenden Inhalt:

Vertiefte Kenntnisse des Boxens und Unboxings in Java

Aus dem durch Dekompilierung erhaltenen Bytecode-Inhalt ist ersichtlich, dass die valueOf(int)-Methode von Integer beim Boxen automatisch aufgerufen wird. Was beim Unboxing automatisch aufgerufen wird, ist die intValue-Methode von Integer.

Andere sind ähnlich, wie Double und Character Friends, die es nicht glauben, können es manuell versuchen.

Der Implementierungsprozess des Boxens und Unboxings lässt sich also in einem Satz zusammenfassen:

Der Boxing-Prozess wird durch Aufrufen der valueOf-Methode des Wrappers während des Unboxings implementiert Prozess Der Prozess wird durch Aufrufen der xxxValue-Methode des Wrappers implementiert. (xxx stellt den entsprechenden Basisdatentyp dar).

3. Fragen im Zusammenhang mit dem Vorstellungsgespräch

Obwohl sich die meisten Menschen über die Konzepte des Ein- und Auspackens im Klaren sind, stießen sie bei Vorstellungsgesprächen und schriftlichen Tests auf Fragen im Zusammenhang mit dem Einpacken. Die Frage des Ein- und Auspackens kann möglicherweise nicht beantwortet werden. Hier finden Sie einige häufige Fragen im Vorstellungsgespräch zum Thema Einpacken/Auspacken.

1. Was ist die Ausgabe des folgenden Codes?

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);
}
}

Vielleicht werden einige Freunde sagen, dass es „falsch“ ausgibt, oder einige Freunde werden sagen, dass es „wahr“ ausgibt. Tatsächlich ist das Ausgabeergebnis jedoch:

wahr
falsch

Warum tritt dieses Ergebnis auf? Die Ausgabe zeigt, dass i1 und i2 auf dasselbe Objekt zeigen, während i3 und i4 auf unterschiedliche Objekte zeigen. An dieser Stelle müssen Sie sich nur den Quellcode ansehen, um die Wahrheit zu erfahren. Der folgende Code ist die spezifische Implementierung der valueOf-Methode von Integer:

public static Integer valueOf(int i) {
if(i >= -128 && i <= IntegerCache.high)
return IntegerCache.cache[i + 128];
else
return new Integer(i);
}

Und darunter die IntegerCache-Klasse. Die Implementierung ist:

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&#39;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() {}
}

Wie aus diesen beiden Codeteilen beim Erstellen einer Ganzzahl ersichtlich ist Wenn der Wert in [-128,127] liegt, wird ein Verweis auf ein Objekt zurückgegeben, das bereits in IntegerCache.cache vorhanden ist. Andernfalls wird ein neues Integer-Objekt erstellt.

Im obigen Code sind die Werte von i1 und i2 100, sodass die vorhandenen Objekte direkt aus dem Cache abgerufen werden, sodass i1 und i2 auf dasselbe Objekt verweisen, während i3 und i4 zeigen jeweils auf unterschiedliche Objekte.

2. Was ist die Ausgabe des folgenden Codes?

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);
}
}

Einige Freunde denken vielleicht, dass das Ausgabeergebnis der obigen Frage dasselbe ist, aber tatsächlich ist es nicht so. Das tatsächliche Ausgabeergebnis ist:

false
false

Was den konkreten Grund betrifft, können Leser die Implementierung von valueOf der Double-Klasse überprüfen.

Vertiefte Kenntnisse des Boxens und Unboxings in Java

Hier werde ich nur erklären, warum die valueOf-Methode der Double-Klasse eine andere Implementierung verwendet als die valueOf-Methode der Integer-Klasse. Es ist ganz einfach: Die Anzahl der ganzzahligen Werte in einem Bereich ist endlich, Gleitkommazahlen jedoch nicht.

Beachten Sie, dass die Implementierung der valueOf-Methode der Klassen Integer, Short, Byte, Character und Long ähnlich ist.

Die Implementierung der valueOf-Methode von Double und Float ist ähnlich.

3. Was ist die Ausgabe des folgenden Codes:

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);
}
}

Die Ausgabe ist:

wahr
wahr

至于为什么是这个结果,同样地,看了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方法)。

以上所述是小编给大家介绍的Vertiefte Kenntnisse des Boxens und Unboxings in Java,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对PHP中文网站的支持!

更多Vertiefte Kenntnisse des Boxens und Unboxings in Java相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn