2013-10-22 10 views
9

Wenn ich den folgenden Code,Warum Java AutoBox nicht int [], um Integer []

  • arrayList1 - ein Element enthält, und es ist ein int[].
  • arrayList2 - nicht kompilieren (Fehler: Der Konstruktor ArrayList<Integer>(List<int[]>) ist nicht definiert)
  • arrayList3 - enthält 7 Elemente und sie sind Integer Objekte

Hier ist der Code:

int[] intArray = new int[]{2,3,4,5,6,7,8}; 
ArrayList arrayList1 = new ArrayList(Arrays.asList(intArray)); 
ArrayList<Integer> arrayList2 = new ArrayList<Integer>(Arrays.asList(intArray)); 

Integer[] integerArray = new Integer[]{2,3,4,5,6,7,8}; 
ArrayList<Integer> arrayList3 = new ArrayList<Integer>(Arrays.asList(integerArray)); 

Frage: Warum schreibt der Compiler die Elemente in nicht auf Integer und Erstelle eine ArrayList<Integer>? Was ist der Grund dafür? Ist das meine Dummheit oder ein anderer Grund?

Antwort

12

Der Unterschied ist int[] ist ein Object, während Integer[] ist ein Array von Referenzen auf Integer Objekt.

Arrays.asList(T...) Methode verwendet variable Argumente eines Typs T ohne obere Grenzen. Die Löschung dieser Methode ist Arrays.asList(Object...). Das bedeutet, dass eine variable Anzahl von Argumenten jedes Typs verwendet werden muss, die sich von Object erstreckt.

int Da kein Object, sondern eine primitive Art, so kann sie nicht als Einzelelement von T[] übergeben werden, während ein int[]Object selbst ist, wird es als erstes Element des Arrays T[] gehen (T... intern ist a T[] nur). Jedoch wird Integer[] als T[] übergeben, wobei jede Referenz in Integer[] als anderes Argument an T[] übergeben wird.

Und selbst wenn Sie argumentieren würden, dass Compiler die Umwandlung von jedem Element int[] Array zu Integer getan haben sollte, wäre das zu viel Arbeit für den Compiler. Zuerst müsste es jedes Array-Element nehmen und es auf Integer boxen, dann müsste es intern Integer[] aus diesen Elementen erstellen. Das ist wirklich zu viel. Es hat bereits eine direkte Umwandlung von int[] zu Object, was folgt. Obwohl ich immer gewünscht habe, dass Java eine implizite Konvertierung von int[] zu Integer[] erlaubt, hätte dies das Leben während der Arbeit mit Generika einfacher gemacht, aber wiederum, so ist die Sprache entworfen.

ein einfaches Beispiel:

Object[] array = new Integer[10]; // this is valid conversion 
Object[] array2 = new int[10];  // this is not 
Object obj = new int[10];   // this is again a valid conversion 

in Ihrem Code So kehrt Arrays.asList(intArray) ein ArrayList<int[]> und nicht ArrayList<Integer>. Sie können es nicht an den ArrayList<Integer>()-Konstruktor übergeben.


Verwandte:

+0

Vielen Dank Rohit. Ich habs! – namalfernandolk

+0

@NamalFernando Gern geschehen :) –

1

Da int[] und Integer[] beide Objekte sind. Zuerst werden primitive int Werte gehalten, die nicht vom Typ Object sind, während zweite Referenzen von Integer Objekten speichert, die vom Typ Object sind.

+0

Ok. Ich habs. Vielen Dank! – namalfernandolk

3

Ein int[] ist nicht dasselbe wie ein Integer[].

An array has as associated Class object. Das Klassenobjekt für ein Array primitiver Ints ist [I. Das Klassenobjekt für ein Array von Integer ist .

Ein Array ist selbst ein Objekt, also konvertiert man zwischen zwei Objekten desselben Typs is an identity conversion. Konvertieren zwischen zwei verschiedenen typisierten Objekten ist nicht - und int[] und Integer[] sind definitiv anders, wie durch den obigen Bytecode belegt.

Schließlich, bedenken Sie, dass Autoboxing nur wirklich gelten würde, wenn there was an associated boxing conversion.

+0

Danke Makoto. Ihre Antwort und Referenzen helfen sehr. – namalfernandolk

+0

Es wäre möglich, eine VM so zu gestalten, dass man Referenz-Lade-/Speicheroperationen auf einem '[I] und ganzzahligen Lade-/Speicheroperationen auf a' [L 'verwenden kann, mit der Einschränkung, dass solche Operationen fehlschlagen können mit einem Tippfehler; Wenn das getan wäre, wäre es möglich, ein 'int []' als ein 'Integer []' zu verwenden. Die größten Schwierigkeiten wären, dass (1) ein 'int []' übergeben würde, um einen 'Integer []' zu erwarten, oder umgekehrt, würde zu einem enormen Geschwindigkeitsverlust führen; (2) ein Versuch, 'null' in einem' [L'zu speichern, könnte einen 'Integer' in etwas, das wie ein' Integer [] aussieht, speichern und zurücklesen ... – supercat

+0

... könnte einen anderen ergeben Objekt von dem, der übergeben wurde. – supercat

2

Technisch ist es natürlich möglich, es zu tun. Das automatische Binden/Unboxing von primitiven Array zu Wrapper Array ist jedoch mehr als das, was Sie erwarten.

Zuerst schauen Sie in das automatische Boxen/Unboxing von Java: Was es tut, ist einfach eine Syntaxzucker, um Sie zu sparen, den primitiven Wrappercode eintippend. z.B.

Integer i = 10; 

Compiler weiß, dass es eine Integer erwartet, aber int stattdessen vorhanden. Deshalb, was der Compiler tun ist, Ihren Code zu übersetzen:

Integer i = Integer.valueOf(10); 

Es tut ähnliche Sache für Unboxing: wenn in Situation, dass es erwartet int aber Integer vorhanden ist, Compiler ersetzen Sie es mit varName.intValue()

Zurück zum Array. Es gibt zwei Probleme, die wir vorhersehen können:

Das erste Problem besteht darin, dass es keine direkte Möglichkeit gibt, von einem int-Array in ein Integer-Array zu transformieren. Sie können argumentieren, dass der Compiler

int[] intArray = ....; 
Integer[] wrapperArray = intArray ; 

zu

Integer[] wrapperArray = new Integer[intArray.size()]; 
for (int i = 0; i < intArray.size(); i++) { 
    wrapperArray[i] = Integer.valueOf(intArray[i]); 
} 

aber das scheint zu viel für einen Syntax Zucker umwandeln kann.

Das zweite große Problem ist, wenn Sie es als Parameter zu einer Methode übergeben, wenn Autoboxing/Unboxing für Array passiert, anstelle der Referenz des ursprünglichen Arrays übergeben wird, übergeben Sie jetzt die Referenz einer Kopie der Original-Array.Wenn Sie den Inhalt des Arrays in Ihrer Methode ändern, wird das ursprüngliche Array nicht beeinflusst. Das kann dir viele Überraschungen bringen.

z.B.

void foo(Integer[] arr) { 
    arr[0] = 0; 
} 

// invoking foo in some code: 
int[] intArr = new int[]{9,8,7,6}; 
foo(intArr); 
// intArr[0] will still be 9, instead of 0 
+0

+1 für die detaillierte klare Antwort. Ich denke, StackOverFlow muss eine Option haben, mehrere Antworten zu akzeptieren. – namalfernandolk

+0

@NamalFernando danke für das Lob. Leider bietet SO keine solche Funktion, aber Sie sind frei, mich mit Bounty zu belohnen;) –

1

arrayList1 ist wirklich eine Liste der Größe ein.

http://ideone.com/w0b1vY

arrayList1.size() = 1 
arrayList3.size() = 7 

Der int [] gegossen auf ein einzelnes Objekt wird. Dieses Objekt kann nicht in Ganzzahl umgewandelt werden.

+1

Vielen Dank. Hast du deine Antwort? Aber meine Sorge war, warum es nicht Autoboxing ist? Wie auch immer, ich habe es von Rohit bekommen. – namalfernandolk

Verwandte Themen