Frage

Ich habe gerade Säge Code ähnlich wie diese:

public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a == b);

        Integer c = 100, d = 100;
        System.out.println(c == d);
    }
}

Wenn RAN, dieser Block von Code ausdrucken:

false
true

Ich verstehe, warum die erste false ist: weil die beiden Objekte separate Objekte sind, so dass die == die Referenzen vergleicht. Aber ich kann nicht herausfinden, warum die zweite Anweisung Rückkehr true? Gibt es eine seltsame Autoboxing Regel, dass Tritte in, wenn der Wert eines Integer ist in einem bestimmten Bereich? Was ist denn hier los?

War es hilfreich?

Lösung

Die true Linie ist tatsächlich von der Sprachspezifikation garantiert. Abschnitt 5.1.7 :

  

Wenn der Wert p eingerahmt wird wahr,   falsch, ein Byte, ein Zeichen im Bereich   \ U0000 zu \ u007f oder ein int oder Kurz   Zahl zwischen -128 und 127, dann lassen   R1 und R2 sind die Ergebnisse von zwei beliebigen   Boxen Umwandlungen von p. Es ist immer   der Fall, dass r 1 == r2.

Die Diskussion geht weiter, was darauf hindeutet, dass, obwohl Ihre zweite Zeile der Ausgabe gewährleistet ist, wird die erste nicht (siehe letzter Absatz zitiert unten):

  

Idealerweise Boxen ein primitiver gegeben   p-Wert würde eine immer Ausbeute   identischer Bezug. In der Praxis wird diese   kann nicht möglich sein, vorhandene   Implementierungstechniken. Die Regeln   oben ist ein pragmatischer Kompromiss. Das   Nachsatz erfordert darüber   bestimmte gemeinsame Werte immer eingerahmt werden   in nicht zu unterscheiden Objekte. Das   Implementierung kann diese zwischenspeichern, träge   oder eifrig.

     

Für andere Werte, diese Formulierung   nicht zulässt, keine Annahmen über die   Identität der boxed Werte auf die   Programmierer Teil. Dies würde es ermöglichen   (Aber nicht erforderlich) Austausch einiger oder   alle diese Referenzen.

     

Damit wird sichergestellt, dass in den meisten üblichen   Fällen wird das Verhalten der   gewünschte, ohne eine ungebührliche Auferlegung   Leistungseinbuße, insbesondere auf   kleine Geräte. Weniger Speicher begrenzt   Implementierungen könnte zum Beispiel,   cachen alle Zeichen und kurze Hosen, wie   auch als ganze Zahlen und sehnt sich in der   Bereich von -32K -. + 32K

Andere Tipps

public class Scratch
{
   public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;  //1
        System.out.println(a == b);

        Integer c = 100, d = 100;  //2
        System.out.println(c == d);
   }
}

Ausgang:

false
true

Yep der erste Ausgang zum Vergleichen von Referenz erzeugt; ‚A‘ und ‚b‘ - das sind zwei unterschiedliche Referenz. In Nummer 1 sind eigentlich zwei Referenzen geschaffen, die ähnlich ist wie -

Integer a = new Integer(1000);
Integer b = new Integer(1000);

Die zweite Ausgabe erzeugt wird, weil die JVM Speicher zu speichern versucht, wenn die Integer in einem Bereich fallen (von -128 bis 127). Am Punkt 2 keine neue Referenz vom Typ Integer ist für ‚d‘ erstellt. Stattdessen ein neues Objekt für die Integer-Typ Referenzgröße ‚d‘ zu schaffen, ist es nur mit zuvor erstellten Objekt referenziert von ‚c‘ zugeordnet. Alle diese werden von JVM getan.

Diese Daten speichern Regeln nicht nur für Integer. für Speicher sparend Zweck zwei Instanzen der folgenden Wrapper-Objekte (während durch Boxen erstellt), werden es immer sein == wo ihre primitiven Werte gleich sind -

  • Boolean
  • Byte
  • Charakter von \ u0000 zu \u007f (7f ist 127 dezimal)
  • Short und Integer von -128 127

Integer-Objekte in einem gewissen Bereich (ich denke, vielleicht -128 bis 127) erhalten im Cache gespeichert und wiederverwendet. Die ganzen Zahlen außerhalb dieses Bereichs jedes Mal ein neues Objekt erhalten.

Ja, es ist eine seltsame Autoboxing Regel, dass Tritte in, wenn die Werte in einem bestimmten Bereich. Wenn Sie eine Konstante zu einem Objektvariablen zuweisen, nichts in der Sprachdefinition sagt ein neues Objekt muss erstellt werden. Es kann ein vorhandenes Objekt aus dem Cache wiederverwendet werden.

In der Tat wird die JVM in der Regel speichert einen Cache von kleinen ganzen Zahlen für diesen Zweck sowie Werte wie Boolean.TRUE und Boolean.FALSE.

Das ist ein interessanter Punkt. In dem Buch Effective Java immer außer Kraft zu setzen schlägt gleich für Ihre eigenen Klassen. Auch, dass Gleichheit für zwei Objektinstanzen einer Java-Klasse zu überprüfen, verwenden Sie immer die Methode entspricht.

public class Scratch
{
    public static void main(String[] args)
    {
        Integer a = 1000, b = 1000;
        System.out.println(a.equals(b));

        Integer c = 100, d = 100;
        System.out.println(c.equals(d));
    }
}

Rückgabe:

true
true

Meine Vermutung ist, dass Java einen Cache von kleinen ganzen Zahlen hält, die bereits sind ‚verpackt‘, weil sie so sehr verbreitet sind und es spart eine verdammt viel Zeit, um die Weiterverwendung ein vorhandenes Objekt als ein neues zu erstellen.

In Java die Box-Arbeiten im Bereich zwischen -128 und 127 für eine ganze Zahl. Wenn Sie mit Zahlen in diesem Bereich können Sie es mit dem Operator == vergleichen. Für Integer außerhalb des Bereichs Objekte haben Sie Verwendung entspricht.

Direkte Zuweisung eines int wörtlichen zu einer Integer Referenz ist ein Beispiel für Auto-Box, wo der wörtliche Wert Codeobjekt Umwandlung vom Compiler behandelt wird.

So während der Kompilierung Phase Compiler wandelt Integer a = 1000, b = 1000; zu Integer a = Integer.valueOf(1000), b = Integer.valueOf(1000);.

Es ist also Integer.valueOf() Verfahren, das gibt uns tatsächlich die Integer-Objekte, und wenn wir auf dem Quellcode von Integer.valueOf() Methode sehen wir eindeutig die Methode Caches integer Objekte im Bereich von -128 bis 127 (einschließlich) sehen.

/**
 *
 * This method will always cache values in the range -128 to 127,
 * inclusive, and may cache other values outside of this range.
 *
 * @param  i an {@code int} value.
 * @return an {@code Integer} instance representing {@code i}.
 * @since  1.5
 */
 public static Integer valueOf(int i) {
     if (i >= IntegerCache.low && i <= IntegerCache.high)
         return IntegerCache.cache[i + (-IntegerCache.low)];
     return new Integer(i);
 }

Also statt der Schaffung und neue integer Objekte Rückkehr Integer.valueOf() die Methode zurückgibt Integer aus dem internen IntegerCache Objekten, wenn die übergebene int wörtlichen größer als -128 und kleiner als 127.

Java-Caches dieser Integer-Objekte, da dieser Bereich von ganzen Zahlen eine Menge in der täglichen Programmierung verwendet wird, die indirekt etwas Speicher speichert.

Der Cache auf der ersten Verwendung initialisiert wird, wenn die Klasse in dem Speicher wegen des statischen Blockes geladen wird. Die maximale Reichweite des Cache kann durch die -XX:AutoBoxCacheMax JVM-Option gesteuert werden.

Dieses Caching-Verhalten ist nicht anwendbar für Integer nur Objekte, ähnlich wie Integer.IntegerCache wir haben ByteCache, ShortCache, LongCache, CharacterCache für Byte, Short, Long, Character auch sind.

Sie können lesen Sie mehr auf meinem Artikel Java Integer Cache - Warum Integer.valueOf (127) == Integer.valueOf (127) wahr .

In Java 5 wurde eine neue Funktion eingeführt, um den Speicher zu sparen und die Leistung verbessern für Integer-Typen Handlings-Objekte. Integer-Objekte werden im Cache gespeichert intern und über die gleichen referenzierte Objekte wiederverwendet werden.

  1. Dies gilt für Integer-Wert in einem Bereich zwischen -127 bis +127 (Max Integer-Wert).

  2. Dieses Integer-Caching funktioniert nur auf Autoboxing. Integer Objekte nicht im Cache gespeichert werden, wenn sie den Konstruktor gebaut verwenden.

Für weitere Einzelheiten pls geht durch unter-Link:

Integer Cache im Detail

Wenn wir den Quellcode Integer obeject überprüfen, werden wir die Quelle valueOf Methode finden wie diese:

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

, die erklären können, warum Integer Objekte, die im Bereich von -128 (Integer.low) bis 127 (Integer.high), sind die gleichen referenzierte Objekte während des Autoboxing. Und wir können sehen, gibt es eine Klasse IntegerCache kümmert sich um die Integer Cache-Array, das eine private statische innere Klasse von Integer Klasse ist.

Es ist ein weiteres interessantes Beispiel kann uns helfen, diese seltsame Situation zu verstehen:

public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {

      Class cache = Integer.class.getDeclaredClasses()[0]; 
      Field myCache = cache.getDeclaredField("cache"); 
      myCache.setAccessible(true);

      Integer[] newCache = (Integer[]) myCache.get(cache); 
      newCache[132] = newCache[133]; 

      Integer a = 2;
      Integer b = a + a;
      System.out.printf("%d + %d = %d", a, a, b); //The output is: 2 + 2 = 5    

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top