Überschreiben von Methoden anhand des Rückgabewerts #338
Labels
No Label
Codegen
confirmed
duplicate
Eclipse-Plugin
Feature Request
generics
in progress
invalid
JavaCompilerCore
needs info
Parser
Trash
Type
Unify
won't fix
works for me
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: JavaTX/JavaCompilerCore#338
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hier geht es um ein Problem zu #294, das mir gerade aufgefallen ist. Der Fix für diesen Bug ist wahrscheinlich nicht optimal implementiert.
Problem 1
Die Substitution der primitiven Typen scheint unabhängig von Referenztypen immer vorgenommen zu werden. Hier müsste man vielleicht überprüfen, ob der primitive Typ zum Wrappertyp passt.
Beispiel:
Dieser Code sollte vermutlich eine Exception werfen, da als Rückgabewert der Funktion offensichtlich java.lang.List inferiert wird. Die hashCode Methode von Object gibt aber ein int zurück und die Methode sollte nicht anhand des Rückgabewerts überladen werden können.
Stattdessen kompiliert der Code folgendermaßen:
Er substituiert wegen der Lösung von #294 int für List, gibt aber weiterhin ein Listenobjekt zurück. Das wirft zur Laufzeit eine Exception.
Problem 2
Generell scheint die Substitution nicht nur bei primitiven Typen zu passieren.
Beispiel
In diesem Fall gibt die
toString()
Methode von Object ein String Object zurück. Diesen Code sollte der Typcheck wahrscheinlich direkt ablehnen. Stattdessen wird auch hier einfach String für Integer substituiert, obwohl Integer zurückgegeben wird.Problem 3
Allgemein ist es aktuell möglich, Methoden anhand des Rückgabewerts zu überladen.
Beispiel:
Dieser Code sollte wahrscheinlich nicht kompilieren.
Es ist auch möglich die genau gleiche Methode mehrmals zu schreiben. Im Bytecode steht genau die gleiche Methode dann einfach zwei mal.
z.B.
Vielleicht wäre es tatsächlich eine bessere Lösung für dieses Problems Bridge Methods zu verwenden. Das wurde ja auch in Bad Honnef von einem Teilnehmer vorgeschlagen.
Also dass der Compiler zusätzlichen Bytecode generiert, der den Methodenaufruf mit dem primitiven Typen in der Signatur auf die Methode mit der Wrapperklasse in der Signatur weiterleitet.
z.B.
Ich glaube das mit den Bridge Methods ist keine gute Idee. Was passiert, wenn man versucht die Klasse von normalem Java-Code aufzurufen?
Meiner Meinung nach sollte nicht viel passieren. Es wird halt eine von beiden Methoden aufgerufen, wahrscheinlich die erste im Bytecode. Ist im dem Fall ja eigentlich auch egal welche aufgerufen wird, oder?
https://github.com/vijayjogi/shshankar1/blob/master/Java%20Generics%20and%20Collections.pdf
Wenn du dir hier mal Abschnitt 3.8 anschaust, macht Java ja prinzipiell das Selbe nur für ein anderes Problem
Ich muss das mal ausprobieren. Bin mir tatsächlich nicht sicher was da passiert.
Also ich habe es jetzt ausprobiert und es entsteht folgender Fehler wenn man versucht die Methode hashCode aufzurufen:
Das überschreiben mit einer Methode mit anderer Signatur scheint also was anderes zu sein, in dem Fall existiert aber auch nur eine Methode innerhalb der Klasse.
Ich hab es auch mal ausprobiert. Es scheint wichtig zu sein, dass man für die Bridge Methode die Flags ACC_BRIDGE und ACC_SYNTHETIC setzt. Dann geht es aber wie erwartet.
Ich lasse diesen Bytecode generieren:
Und aufrufen kann ich es dann wie erwartet:
Ich hab das ganze Beispielprojekt mal in Anhang gepackt
Interessant, hab noch nie was von den Flags gehört aber du hast recht, jetzt funktioniert es. Was sagst du dazu @pl ?
Hallo Julian, ich habe mir das eben von Daniel erklären lassen. Leider kann ich nicht ganz nachvollziehen welchen Vorteil Du in den Bridgemethoden siehst. Letzlich passiert doch genau das gleiche, oder welchen Vorteil siehst Du?
Ja, das stimmt schon. Das Ergebnis ist dasselbe. Auf mich wirkt es weniger anfällig für Bugs, als die Typen im Bytecode zu substituieren. Aber keine Ahnung, ob das wirklich ein Vorteil ist