Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
also new Object() ist meiner Meinung nach eine anonymen Klasse, oder hat die einen Namen? Und ich dachte immer Objekte werden mit Ihrem Standardwert, also null, initialisiert, wenn man ihr keinen Wert zuweißt?
Vielen Dank für Eure Hilfe! Das mit der anonymen Klasse war gar nicht so mein Problem. Mein Problem war eher, warum dieses Objekt nicht mit null initialisiert wird! :wink: Ich wollte es eigentlich nur verstehen! Es muß keine null rauskommen! Weil unerwarteter Weise irgendwelche Hyroglyphen auftauchten !
eine so DEKLARIERTE VARIABLEe wird mit null initialisiert,
System.out.println(o) führt dann auch zur Ausgabe null,
aber in deinem Beispiel gehts ja gar nicht um Variablendeklaration,
eine Variable tritt da gar nicht auf (höchstens eine anonyme, namenlose Variable )
stattdessen wird ein Objekt erzeugt, ob nun von der Klasse Objekt oder von einer anderen Klasse,
und wenn ein Objekt erzeugt wird, dann ist das logischerweise nicht null,
null als Objekt kriegt man nur wenn man auch explizit 'null' sagt,
einer Variablen kann man dagegen nicht ansehen was sie enthält, da kann auch null drinstecken, insbesondere ganz am Anfang
ein Objekt kann nicht initialisiert werden, entweder es ist da oder nicht
Das ist die toString() Methode von Object... - die Ausgabe ist insb. beim Debuggen sinnig, um zu gucken, wann welche Objekte tatsächlich identisch sind und wo die identischen Objekte überall so auftauchen.. da nie zwei Objekte die gleiche Identifikationsnummer haben können.
Daß stimmt nicht, da die hash-Funktionen nicht eineindeutig sind.
Auch verbietet es niemand folgendes zu schreiben:
Code:
public class Test {
public static void main(String[] args) {
class C extends Object {public int hashCode() {return 42;}}
System.out.println(new C());
System.out.println(new C());
}
}
Wieso können zwei Objekte den gleichen Hash erhalten ?
Klar kann beim ersten ermitteln ein bereits vergebener hash rauskommen,
aber damit ist ja das Hashing nicht beendet.
Java Hashmaps und andere Container können das doch auch.
(anderen Hash ermitteln bzw Tabelle vergrößern)
Bei einer Hash-Funktion geht es allgemein darum, eine lange Eingabe (zum Beispiel einen Text) in eine kurze Ausgabe (den Hash-Wert des Textes) zu verwandeln.
@ Wildcard: Wieso muss man die Objekte dafür kennen ?
Kannst Du das mal etwas ausführen ?
@ byto: Ich weiß, dass es bei Hashfunktionen zu Kollisionen kommen kann.(ist zwar ein paar Jahre her, dass ich welche geschrieben habe,
aber alles vergisst man ja nun auch nicht)
Ja nach Verfahren müssen die dann aufgelöst werden.
Aber ich rede doch gar nicht davon, dass es beim Hashing zu gleichen Werten kommt.
Ich sagte "Objekte", und das meinte ich auch.
Mir geht es darum, wie java mit dem Zeug arbeitet, und nicht um eine Nachhilfestunde über Hashing.
Ich dachte hier kann vielleicht jemand den Mechanismus den java da anwendet erklären, oder einen passenden Link zur Verfügung stellen.
Ich versteh das Problem nicht... die Methode hashcode besitzt jedes Objekt - sofern diese nicht überschrieben wird bzw. zumindest die Klasse Object selbst generiert einen hashwert der möglichst einzigartig ist. Das garantiert natürlich nicht, dass nicht doch ein zweites Objekt genau den gleichen hashwert erzeugt, daher können auch zwei Objekte den gleichen hashwert haben.
Hat jemand nen Wahrscheinlichkeitswert dafür? .. die hashcode Methode selbst ist im übrigen native - so kann man also nicht mal schnell nachgucken, wie genau diese implementiert wurde
Wenn jedes Objekt seinen eigenen Hash berechnet und die anderen Objekte nicht kennt, wie sollte dann eine Kollisionsprüfung stattfinden? Das Objekt kenn ja nur den eigenen Hashwert.
Daher kann ein Hash auch nicht eindeutig sein.
Roar hat glaub ich schon gesagt, wie die hashCode() in Object arbeitet. Sie liefert einfach die interne Speicheradresse des Objekts zurück. Somit können natürlich erstmal zwei Objekte nicht den gleichen "HashCode" haben. Wenn da nicht der böse GC wäre, der Objekte auch mal verschiebt. Dadurch ändert sich die Speicheradresse des Objekts. Wenn Du also Objekte als Keys in einem Hashtable aufnimmst, dann kann es dadurch zu Problemen kommen aufgrund der Kollisionen. Ähnliche Probleme hast Du bei Sets, denn die benutzen die equals() (welche wiederum hashCode() verwendet) um zu gucken, ob ein gleiches Objekt schon in der Menge steht.
Die hashCode() von String arbeitet übrigens anders. Bei langen Strings werden dann einfach nur alle x Zeichen betrachtet, der Rest fliegt raus. Und dann wird das ganze irgendwie noch multipliziert, weil das irgendwie die Gefahr der Kollisionen senkt.
Soweit mir bekannt, ist die einzige Möglichkeit gleiche Hashwerte zu erhalten,
wenn man eine Architektur einsetzt, deren Speicherbereich sich nicht mit einem Integer abbilden lässt.
Das die GC da Problem macht wusste/weiß ich nicht.
Bei den Hashmaps etc. ist es aber doch gerade so, dass auch bei nicht 100%iger identität
der gleiche Hashcode ermittelt wird.
"equals()" wird benutzt um zwei Objekte zu vergleichen.
Prüft man darin auf die Identität des Speichers (also wirklich das gleiche Objekt) kann man keine
Liste mehr sinnvoll durchsuchen, weil man für den positiven Vergleich ja das Objekt aus der Liste braucht.
Standardmäßig (also java.lang.Object) wird die Speichergleichheit geprüft.
Also wird für abgeleitete Klassen "equals()" angepasst um auf die Werte innerhalb der Objekte zu reagieren.
Integer:
Code:
public boolean equals(Object obj) {
if (obj instanceof Integer) {
return value == ((Integer)obj).intValue();
}
(verwendet also nicht "hashcode()")
Hashcodes werden zur Performanceerhöhung eingesetzt. Mit der passenden "equals()" Methode kann man
zwar jetzt prima iterieren und vergleichen, aber der schnellere Zugriff über die Hashcodes geht nicht.
Also wird der Hashcode in Abhängigkeit der enthaltenen Werte gebildet.
Dann kann man wieder den Hashcode zum Listenzugriff verwenden.
Beim Integer ist das ein einfaches "return value". (>> zwei Integer mit gleichem Wert liefern also wieder den gleichen
Hashcode, so wie das von Object verlangt wird)
Also :
equals() positive >> hascode muss übereinstimmen
equals() negative >> hascode darf übereinstimmen, sollte aber besser nicht (performance)
Object -> equals() testet die Identität, hashCode() basiert auf Speicheraddresse.
"Andere" -> equals() teste die Wertegleichheit, hashCode() basiert auf den Werten des Objects
Mehrere "Objects" sollten also nur im Extremfall "zuviel Speicher" (und GC Probleme ?) den gleichen
hashCode haben.
Bei anderen Klassen ist der hashCode bewusst gleich, um Listenfunktinen etc. zu ermöglichen.
Wäre jetzt noch lustig einen Test zu machen, der eine Liste mit echten Objects füllt und zeigt, dass die Gleicheit
nur bei echter Identität erfüllt ist.
Wird aber irgendwie schwer, weil Objects ja nichts anderes haben um sie zu identifizieren, als den hashCode ?