Compiler löscht meine Typkonvertierung?

8

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:

%Vor%

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:

%Vor%

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)

%Vor%

Und es hat sich immer noch beschwert, dass ich ein Long bereitgestellt habe. Das war seltsam. Dann habe ich das versucht:

%Vor%

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?

    
Dana 21.09.2016, 00:12
quelle

1 Antwort

10

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.

    
Andrew Eisenberg 21.09.2016, 00:30
quelle

Tags und Links