Java:
public class Inferenz {
public class A {}
public class B extends A {}
public class C extends A {}
static private <T > T ret1 (T e , T z) { return e ;}
static private <T ,U > T ret2 (T e , U z) { return e ;}
public static void main(String[]args) {
B b = (B) ret1 ( new B () , new C () ) ; // (4)
C c = (C) ret1 ( new B () , new C () ) ; // (6)
c = (C) ret2 ( new B () , new C () ); // (12)
}
}
Begründung für die Zuweisung (4) : Zuweisung funktioniert, da wir als Rückgabetypen ein A bekommen. Dieser lässt sich dadurch ermitteln, dass der speziellste
gemeinsame Obertyp die Klasse A ist. Natürlich würde es so alleine nicht funktionieren. Also machen wir ein Downcast zum Typ B, da wir dem Compiler versichern,
dass ein B zurückgegeben wird und wir dann B=B hätten, was gehen würde. Jetzt ist meine Vermutung: Auch in der Laufzeit wird es keine Probleme geben, da unser return ja den ersten Parameter zurückgibt, und somit käme tatsächlich eine Instanz der Klasse B raus und wir können es aus diesem Grund auch einem B tatsächlich zuweisen. Downcasts sind ja in der Regel riskant und warum wird bei der (4) kompiliert und bei der Zuweisung (12) dann doch nicht.
Meine Vermutung dazu ist folgende: Da die beiden Typparameter T und U unabhängig voneinander sind, weiß der Compiler sicher, dass der Rückgabetyp hier ein
B ist. Da wir dann ja dieses B auf ein C casten, lässt dies der Compiler nicht zu, da wir nicht eine Unterklasse zu einer anderen Unterklasse casten können. Lediglich ein Upcast zur Klasse A wäre möglich, jedoch würde diese Zuweisung ebenso nicht kompilieren, da dann eine Instanz von der Unterklasse, also C, eine Instanz der Oberklasse, also A bekäme.
Nun zu meiner Vermutung bei der (6): Von B und C wird ein gemeinsamer und speziellster Obertyp gesucht, da es ja nur einen Typparameter T gibt.
Der Compiler findet heraus, dass es sich um den gemeinsamen und speziellsten Typen A handelt. Dieses A casten wir runter auf ein C, da wir als Entwickler dem Compiler versichern, dass es sich um einen Typen der Klasse C handelt. Die Zuweisung compiliert zwar, jedoch wird zur Laufzeit festgestellt, dass tatsächlich kein Typ von C zurückgegeben wird, sondern ein Typ von A, oder mache ich hier ein Fehler ? Es könnte auch B zurückgegeben werden in der Laufzeit, beides würde aber zu einem Laufzeitfehler führen.
Ich würde mich sehr freuen, wenn ihr mich korrigieren bzw. aufklären könntet, damit ich den Sachverhalt korrekt verstehe.
Vielen Dank im Voraus für alle, die mir behilflich sein können.