tutorials.de Buch-Aktion 05/2012
Like Tree4Danke
  • 1 Beitrag von Johannes7146
  • 1 Beitrag von Johannes7146
  • 1 Beitrag von Kai008
  • 1 Beitrag von THMD
ERLEDIGT
JA
ANTWORTEN
8
ZUGRIFFE
341
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    hansmueller hansmueller ist offline Mitglied Silber
    Registriert seit
    Sep 2008
    Beiträge
    78
    Hallo,

    ich habe ein Verständnisproblem bei dem Operator "==".
    Wenn ich es richtig verstanden habe, wird bei Objekten mit den Operator "==" nicht der Inhalt, sondern die Reverenz (also der Speicherort) verglichen.
    Zwei verschieden Objekte sollten daher immer "false" liefern, auch wenn deren Inhalt gleich ist. ==> Tut es aber nicht immer

    Folgendes Beispielprogramm

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    public class MainProg
    { 
        public static void main(String[] args)
        {
            Integer x = 1;
            Integer y = 1;
            
            Double e = 1.0;
            Double r = 1.0;
            
            Long c = 1l;
            Long v = 1l;
            
            Float u = 1.0f;
            Float i = 1.0f;
            
            System.out.println(x == y);
            System.out.println(x.equals(y));
            System.out.println("------------");
            System.out.println(e == r);
            System.out.println(e.equals(r));
            System.out.println("------------");
            System.out.println(c == v);
            System.out.println(c.equals(v));
            System.out.println("------------");
            System.out.println(u == i);
            System.out.println(u.equals(i));
        }
    }

    liefert folgende Ausgabe:

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
    true
    true
    ------------
    false
    true
    ------------
    true
    true
    ------------
    false
    true

    Müsste theoretisch nicht bei allen Vergleichen mit "==" ein "false" herauskommen.

    Warum ist das nicht so?

    MfG
    hansmueller
     

  2. #2
    Avatar von Johannes7146
    Johannes7146 Johannes7146 ist offline Goldschnabel
    Registriert seit
    Sep 2007
    Ort
    Gütersloh
    Beiträge
    736
    Bei dieser Variante kommt immer das heraus, was du erwartest:

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    public static void main(String[] args) {
            Integer x = new Integer(1);
            Integer y = new Integer(1);
     
            Double e = 1.0;
            Double r = 1.0;
     
            Long c = new Long(11);
            Long v = new Long(11);
     
            Float u = 1.0f;
            Float i = 1.0f;
     
            System.out.println(x == y);
            System.out.println(x.equals(y));
            System.out.println("------------");
            System.out.println(e == r);
            System.out.println(e.equals(r));
            System.out.println("------------");
            System.out.println(c == v);
            System.out.println(c.equals(v));
            System.out.println("------------");
            System.out.println(u == i);
            System.out.println(u.equals(i));
        }

    Bleibt zu klären wo der unterschied zwischen:
    Code java:
    1
    
    Integer x = 1;
    und
    Code java:
    1
    
    Integer x = new Integer(1);
    liegt.

    Ich hätt eigentlich auch erwartet das in beiden Fällen eine eigene Instanz angelegt wird.
    Außerdem warum verhält es sich bei Double und Float nicht so, sonder nur bei Integer und Long?

    Fragen über Fragen, evtl. postet ja gleich noch jemand der mehr Ahnung hat als wir beiden.
    hansmueller bedankt sich. 
    Wenn mein Beitrag dir geholfen hat, würde ich mich sehr über eine positive Bewertung oder ein Danke freuen
    Gruß Johannes
    ::: Homepage :::

  3. #3
    Avatar von Johannes7146
    Johannes7146 Johannes7146 ist offline Goldschnabel
    Registriert seit
    Sep 2007
    Ort
    Gütersloh
    Beiträge
    736
    Hab gerade mal noch ein wenig herumgetestet.
    Wenn du eine Variable über
    Code :
    1
    
        Integer x = 1;
    dann vergleicht der == Operator den Inhalt der Variable.
    Wenn du über den über NEW instanzierst hast, vergleicht er die Instanzen.

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    
    package test;
     
    public class GleichGleich {
        public static void main(String[] args) {
     
            Integer a = new Integer(1);
            Integer b = new Integer(1);
            
            Integer c = 1;
            Integer d = 1;
            
            System.out.println("a und b");
            vergleichen(a,b);
            System.out.println("c und d");
            vergleichen(c,d);
            
            
            System.out.println("a und c");
            vergleichen(a,c);
            System.out.println("b und d");
            vergleichen(b,d);
            
            
            System.out.println("c und a");
            vergleichen(c,a);
            System.out.println("d und b");
            vergleichen(d,b);
        }
     
        public static void vergleichen(Integer x, Integer y) {
            // x hochzählen
            x += 1;
     
            // Inhalte ausgeben
            System.out.println(x+" == "+y+" : "+(x==y));
     
            // x runterzählen
            x -= 1;
     
            // Inhalte ausgeben
            System.out.println(x+" == "+y+" : "+(x==y));
            System.out.println("");
        }
     
    }

    Ausgabe:
    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    
    a und b
    2 == 1 : false
    1 == 1 : false
     
    c und d
    2 == 1 : false
    1 == 1 : true
     
    a und c
    2 == 1 : false
    1 == 1 : true
     
    b und d
    2 == 1 : false
    1 == 1 : true
     
    c und a
    2 == 1 : false
    1 == 1 : false
     
    d und b
    2 == 1 : false
    1 == 1 : false
    Geändert von Johannes7146 (17.03.10 um 13:24 Uhr)
    hansmueller bedankt sich. 
    Wenn mein Beitrag dir geholfen hat, würde ich mich sehr über eine positive Bewertung oder ein Danke freuen
    Gruß Johannes
    ::: Homepage :::

  4. #4
    hansmueller hansmueller ist offline Mitglied Silber
    Registriert seit
    Sep 2008
    Beiträge
    78
    Schon sehr merkwürdig.

    Bei Boolean hat man den gleichen Effekt.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    public class MainProg
    { 
        public static void main(String[] args)
        {
            Boolean j = true;
            Boolean k = true;
            
            Boolean n = new Boolean(true);
            Boolean m = new Boolean(true);
                    
            System.out.println(j == k);
            System.out.println(j.equals(k));
            System.out.println("------------");
            System.out.println(n == m);
            System.out.println(n.equals(m));
        }
    }
    liefert
    Code :
    1
    2
    3
    4
    5
    
    true
    true
    ------------
    false
    true

    Vielleicht liegt es daran, daß es sich eigendlich um elemtare Typen handelt, welche nur von einer Wrapperklasse umgeben sind. Elementare Typen sind keine Klassen bzw. Objekte im eigendlichen Sinn, sondern stehen außerhalb des objektorientierten Konzepts von Java. (Ich hoffe, daß stimmt so, wie ich es geschrieben habe.)

    Dieses inkonsequente Verhalten wird dadurch aber auch nicht geklärt.

    Es wäre wirklich interessant zu wissen, ob dieses Verhalten gewollt ist und eine Logik dahintersteckt, oder ob es sich einfach um einen Bug handelt?
     

  5. #5
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Um noch eine Theorie in den Raum zu werfen:
    Es gibt bei Strings einen Pool, in dem zuerst geschaut wird, ob bereits eine Instanze mit dem Wert existiert, und wenn ja, diese verwendet wird.
    Falls man new verwendet wird das aber ignoriert, vielleicht ist es bei primitiven Typen genauso.
    hansmueller bedankt sich. 
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

  6. #6
    hansmueller hansmueller ist offline Mitglied Silber
    Registriert seit
    Sep 2008
    Beiträge
    78
    Die Erklärung hört sich gut an und könnte ein Schritt in die richtige Richtung sein.

    Code :
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    
    public class MainProg
    { 
        public static void main(String[] args)
        {
            String x = "Hallo";
            String y = "Hallo";
            
            String e = new String("Hallo");
            String r = new String("Hallo");
                    
            System.out.println(x == y);
            System.out.println(x.equals(y));
            System.out.println("------------");
            System.out.println(e == r);
            System.out.println(e.equals(r));        
        }
    }
    ergibt
    Code :
    1
    2
    3
    4
    5
    
    true
    true
    ------------
    false
    true

    Es bleiben aber noch viele Fragen offen.

    Warum gibt es für Gleitkomma-Typen keinen solchen Pool?
    Und warum das unterschiedliche Verhalten bei den verschiedenen Arten der Instanziierung? (Einmal mit "new", einmal ohne.)
     

  7. #7
    hansmueller hansmueller ist offline Mitglied Silber
    Registriert seit
    Sep 2008
    Beiträge
    78
    Bezüglich der Sache mit dem String-Pool habe ich folgendes im Netz gefunden:
    http://www.javaschubla.de/2007/javaerst0150.html
    http://www.java-blog-buch.de/0302-strings-vergleichen/

    Kann wirklich sein, das es für boolean- und Integer-Typen auch einen solchen Pool gibt.

    Warum dann aber nicht für Gleitkomma-Typen?
     

  8. #8
    THMD THMD ist offline Mitglied Gold
    Registriert seit
    Sep 2005
    Beiträge
    122
    Moin,

    also das ursprüngliche Problem hat mit den Pools so direkt erst mal gar nix zu tun. Grundlage für das Verhalten sind die Konventionen für das Autoboxing. Dabei werden laut Sprachspezifikation bestimmte Werte in identische Objekte umgewandelt. Garantiert wird das für die beiden boolean, alle byte, chars von \u0000 to \u007f sowie int und short von -128 bis 127. Für alle anderen Werte wird es nicht garantiert aber der Abschnitt in der Spec enthält noch die Anmerkung, dass im Idealfall alle Werte auf das gleiche Objekt zeigen sollten - was zumindest für long auch geht (aber auch dort nur im Bereich -128 bis 127).

    Wenn man Vergleiche außerhalb der von der Spec garantierten Bereiche durchführt (z.B. Integer 512) kann true rauskommen, muss aber nicht (zumindest bei meiner Sun VM tut es das nicht). Im Endeffekt sollten Objekte immer mit equals() verglichen werden, wenn es um die Gleichheit geht, ohne irgendwelche Vermutungen anzustellen ob die Dinger nun identisch sind oder nicht.
    For other values, this formulation disallows any assumptions about the identity of the boxed values on the programmer's part. This would allow (but not require) sharing of some or all of these references.
    Und die Pools sind wieder eine andere Geschichte. Tatsächlich gibt es einen "klassenübergreifenden Pool" nur für Stringliterale (alles zwischen " ") - alle anderen Konstanten befinden sich in einen Pool pro Klasse. Über den Stringpool werden gleiche Stringliterale in den Klassen kanonisiert -> gleiche Werte werden durch ein identisches Objekt repräsentiert. Man kann auch zur Laufzeit erzeugte Strings mittels der intern() Methode kanonisieren. Diese schaut, ob es im Pool bereits ein gleicher (equals) String enthalten ist. Wenn ja liefert sie eine Referenz auf diesen String zurück. Wenn nein, wird ein gleichartiger String im Pool aufgenommen und eine Referenz auf diesen zurückgeliefert. Das Problem bei intern() ist, dass nicht spezifiziert ist, was passiert, wenn der String-Pool "voll läuft". Einige VM's steigen dann wohl mit einer OutOfMemory Exception aus. Die aktuellen Sun-VM's verwalten den Pool in einem speziellen Speicherbereich, der Permanent Generation auf dem auch eine Garbage Collection stattfindet - dadurch werden Einträge des Stringpool, die nirgends mehr verwendet werden entsprechend entfernt.

    hth
    THMD
    hansmueller bedankt sich. 
    If Java had true garbage collection, most programs would delete themselves upon execution. (Robert Sewell)

  9. #9
    hansmueller hansmueller ist offline Mitglied Silber
    Registriert seit
    Sep 2008
    Beiträge
    78
    Danke THMD,

    das bringt Licht ins Dunkle.

    Für die, die es Interessiert habe ich noch folgende Links bezüglich Autoboxing gefunden:
    http://openbook.galileodesign.de/jav..._001.htm#t2t36
    http://www.java-blog-buch.de/0607-autoboxing/

    MfG
    hansmueller
     

Ähnliche Themen

  1. AutoIt "Ist nicht gleich" Operator gesucht
    Von YannikTold im Forum Sonstige Sprachen
    Antworten: 4
    Letzter Beitrag: 15.01.11, 11:00
  2. Antworten: 4
    Letzter Beitrag: 25.08.10, 19:13
  3. Wie benutze ich "operator Funktion()"?
    Von Jennesta im Forum C/C++
    Antworten: 3
    Letzter Beitrag: 13.06.10, 14:16
  4. Antworten: 6
    Letzter Beitrag: 02.05.09, 18:11
  5. Operator "AND" und Probleme bei Abfrage
    Von Tservarius im Forum PHP
    Antworten: 1
    Letzter Beitrag: 17.10.04, 21:49

Stichworte