Ich bin verwirrt darüber, was ich tun musste, damit dieser Code funktioniert. Es scheint, als ob der Compiler eine Typkonvertierung, die ich brauchte, wegoptimiert hat, oder es gibt noch etwas, was ich hier nicht verstehe.
Ich habe verschiedene Objekte, die in der Datenbank gespeichert sind und die Schnittstelle Foo
implementieren. Ich habe ein Objekt, bar
, das Daten enthält, die ich verwende, um meine Foo
-Objekte abzurufen. bar
hat folgende Methoden:
Ich übergebe die Klasse und ID an eine Methode mit dieser Signatur, die an Hibernate delegiert, die das Subjekt basierend auf seiner Klasse und ID abruft:
%Vor% Es gibt verschiedene Implementierer von Foo
, und einige dieser Hibernate-Objekte haben eine Long
id und andere haben eine Integer
id. Obwohl diese Methode entweder akzeptiert, weiter unten ist es besser, die richtige zu haben. Als ich versuchte, get()
für ein Objekt mit einer Integer
id wie folgt aufzurufen, bekam ich verständlicherweise einen Fehler, dass ich ein Long
angegeben hatte, wo ein Integer
benötigt wurde:
Hier gibt es kein Problem mit dem Ruhezustand, ich muss nur ein Integer
angeben, für das eine Integer
id erforderlich ist, und ein Long
, für das eine Long
id erforderlich ist. Also habe ich eine Methode zu bar
, hasLongId()
hinzugefügt und folgendes versucht: (An dieser Stelle magst du denken, das ist kein gutes Design, aber das ist jetzt nicht meine Frage)
Und es hat sich immer noch beschwert, dass ich ein Long
bereitgestellt habe. Das war seltsam. Dann habe ich das versucht:
Gleicher Fehler! Wie kann das sein? Also bin ich im Debugger durchgegangen und ja, es ist durch intValue()
und auch durch den Integer
-Konstruktor gegangen, aber dann war in der get-Methode der übergebene Parameter tatsächlich ein Long
- das gleiche Long
-Objekt das wurde von getFooId()
zurückgegeben.
Ich verstehe nicht, was passiert, also versuche ich einfach verschiedene Dinge:
%Vor%und
%Vor%Und schließlich:
%Vor%Dieser funktioniert. Offenbar hat das etwas mit dem ternären Operator zu tun. Aber warum? Kann jemand erklären, was hier passiert ist?
Dies ist eine großartige Frage und geht auf die wesentlichen Details der Semantik des ternären Ausdrucks ein. Nein, dein Compiler ist nicht kaputt oder spielt Tricks auf dich.
Wenn in diesem Fall die Typen des zweiten und dritten Operanden des ternären Ausdrucks long
und int
sind, dann ist der resultierende Typ immer long
. Dies ist auf binäre numerische Werbung .
Laut JLS (Java-Sprachspezifikation) :
..., binäre numerische Heraufstufung wird auf die Operandentypen angewendet, und der Typ des bedingten Ausdrucks ist der hochgestufte Typ des zweiten und dritten Operanden.
Die Werte werden aufgrund der Regel # 1 von Binary Numeric Promotion entpackt:
Wenn ein Operand ein Referenztyp ist, wird er einer Unboxing-Konvertierung unterzogen
Was bedeutet dies im Wesentlichen, dass, wenn Sie einen ternären Ausdruck haben, der resultierende Typ des Ausdrucks statisch (zur Kompilierungszeit) bestimmt werden muss. Der zweite und der dritte Operand müssen in einen einzigen Typ umgewandelt werden, der der Typ des Ausdrucks ist. Wenn beide Operanden ein numerischer Typ sind, wird die binäre numerische Heraufstufung aktiviert, um den endgültigen Typ des Ausdrucks zu bestimmen.
Tags und Links java static-typing