Inferenz JAVA

mrStudent

Mitglied
Java:
public  class  Inferenz {
 
class A{}
class B{}   extends
class C extends B{}
class D extends B{}
class E extends C{}
interface Feld<T>{};
class FeldFix<T> implements Feld<T>{ FeldFix ( int i ) { } ; }
 
<T> T erste ( Feld <? super T> f1 , Feld <? extends T> f 2 ) {T r=null ; return r ; }
<S , T> S [ ] zweite (T [ ] a , Feld <? extends S> b ) {S [ ] s f = null ; return s f ; }

void doit ( ) {
B b = erste ( new FeldFix<B>(3) , new FeldFix<D> ( 3 ) ); //1
Object o = erste ( new FeldFix<C>(3) , new FeldFix<B> ( 3 ) ); //2
B d = erste ( new FeldFix<C>(3) , new FeldFix<C> ( 3 ) ); //3
E e = erste ( new FeldFix<C>(3) , new FeldFix<C> ( 3 ) ); //4
C [ ] [ ] ca = zweite ( new D[ 3 ] , new FeldFix<E[ ] > ( 3 ) ) ; //5
    }
}


Ich habe eine Frage zu diesem Code:
Kann mir jemand erklären, wie die Rückgabetypen in der Methode doit() zustande kommen ?

Normalerweise kannte ich es so, dass bei <? super T> die Obertypen von T oder T selber in Fragen kommt und bei <? extends T> der Untertyp von T oder T selber in Frage kommt. Hier hat es jedoch mit dieser Herangehensweise nicht geklappt, sodass ich die Rückgabetypen auf Papier ohne IDE leider nicht richtig erkannt habe.

Erst als ich auf eclipse den Code reinkopiert habe, merkte ich, an welchen Stellen die Zuweisung funktioniert und wo nicht. Beispielsweise die Zuweisung //1 habe ich leider falsch gehabt.

Würde mich sehr freuen, wenn wir jemand dies erklären könnte. Vielen Dank im Voraus.
 
Zuletzt bearbeitet:
Als erstes ist das kein gültiger Java Code.

Wenn man Code postet, dann bitte etwas auf die Qualität achten so dass sich das keine Fehler einschleichen. Und dann auch auf eine gute Formatierung achten. Du erwartest, dass sich Leute den Code ansehen um Dir zu helfen und bei der Qualität wird dazu kaum jemand bereit sein.

  • Zeile 4 -> Was soll da das extends?
  • Zeile 11 -> "f 2"? Soll dass f2 sein?
  • Zeile 12 -> Was soll da dieses "s f" - Das ist kein gültiger Variablenname. Also entweder sf oder s_f.

Ansonsten hast Du ja zwei Parameter bei erste. Der erste hat ? super T und der zweite ? extends T
//1 hat da dann B und D -> D erbt von B, daher geht das. T kann B sein.
//2 hat C und B -> C erbt von B, daher gibt es da keine Möglichkeit, dies zu erfüllen.
//3 hat C und C -> Das passt, da ja beides C ist. T ist C und B ist eine Superklasse von C
//4 hat C und C -> Das passt von den Parametern aber da kommt ja kein E zurück. T soll aber eine Superklasse von C sein.
//5 wäre wieder ok, Denn der Typ beim zweiten Parameter soll vom Typ des Arrays abgeleitet sein. Und E extends D.
 
Tut mir Leid für die Fehler, das liegt vermutlich daran, dass dies erst mein zweiter Beitrag in diesem Forum ist. Ich danke dir trotzdem, dass du dir es angeschaut hast. Ich werde es nächstes mal besser kontrollieren, ob alles korrekt ist.

Deine Erläuterungen waren sehr hilfreich, könntest du jedoch noch genauer darauf eingehen, welche Schritte du machst, um solch ein Problem zu lösen. Also ich meine, was du bei der Zeile 15 zum Beispiel in kleineren Schritten tust, um dort zur endgültigen Entscheidung zu gelangen. Ich möchte nämlich das Prinzip der Vorgehensweise besser verstehen.

Also wie genau weißt du, welche Typen in Frage kommen und welche kannst du direkt ausschließen. Inwiefern spielen hier die Typeinschränkungen <? extends T> und <? super T> eine Rolle.

Ich bin ehrlich, es hat leider noch nicht ganz klick gemacht bei mir.

Ich danke dir im Voraus für deine Hilfsbereitschaft.
 
Ich versuche, morgen Zeit zu einer Erläuterung zu finden. Bin leider nur noch auf dem Smartphone online und da ist sowas schwer zu erläutern, da dann auch Links mit rein müssen zur Vertiefung.
 
Ich denke, ich tgeile die Erläuterung etwas auf. Das erste ich mehr eine visuelle Erklärung. Diese ist nicht exakt und dient nicht der Erläuterung selbst. Das kann helfen für einen ersten Überblick aber ist nicht exakt und erhebt keinerlei Anspruch auf Vollständigkeit oder Korrektheit.

Wir haben abgeleitete Klassen: Das stellen wir uns als Baum vor. In der Wurzel haben wir Object und dann haben wir abgeleitete Klassen, Also etwas wie:
Object -> A -> B -> C -> D -> E -> F
Die Pfeile sind also jetzt nicht die "extends" Pfeile sondern umgedreht. Dadurch haben wir - wenn wir bei den Pfeilen die "-" weglassen etwas wie:
Object > A > B > C ....

Das ist doch super. In einer Kiste, in die "Object" rein gehören, passen also auch A, B, C, ... rein. Denn Object ist ja "größer" 🙂

Jetzt können wir uns bei dieser Schreibweise (die mir etwas im Herzen weh tut, aber egal - wir wollten nicht exakt sein) uns überlegen, was denn da ein ? super C bzw. ? extends C bedeutet:

Code:
                |=== ? extends C ==>
Object > A > B > C > D > E > F
  <== ? super C ==|

extends C bedeutet, dass die Klasse von C erben muss und das wären dann ja D, E, F, ... und C selbst gehört auch dazu ...
super C bedeutet, dass es eine Superklasse von C sein muss, also C muss davon erben ...

Wenn man jetzt vorgaben hat, wo hier etwas vorgegeben wird, dann können wir es einmalen. Also wir haben bei "? extends T" ein B und bei "? super T" ein E vorgegeben. Das können wir dann ja einmalen:

Code:
Object > A > B > C > D > E > F
            |==================>
<=========================|

Dann sehen wir eine Schnittmenge - B, C, D und E erfüllen diese Voraussetzungen.

Jetzt kommt die Zuweisung ins Spiel. Kann dies denn zugewiesen werden?
Wenn ich da ein Object, A, B, C, D oder E habe, dann gibt es Möglichkeiten. Wenn ich es einer E Variable Zuweisen will, dann ist klar: Es kommt nur noch E in Frage, denn alles andere ist ja "zu groß" und passt da nicht rein.
Wenn ich es einer F Variable zuweisen will: Das geht nicht - F ist zu klein. Da findet sich also kein passender Typ.

Das wäre so eine rein bildliche Vorstellung, die ich mit überlegt habe. Das ist aber wirklich nur eine visuelle Überlegung die dem Verständnis helfen soll und daher nicht an Anspruch nimmt, Vollständig oder korrekt zu sein!

Ich werde nun versuchen, Type Inference noch korrekt und vollständig zu beschreiben, wobei ich da evtl. auch einen guten Link zu finden werde. Irgend wer muss das ja doch schon einmal gut erläutert haben, so dass ich da jetzt nicht die JLS Kapitel 18 aufbereiten muss.
Aber da ist halt im Detail beschrieben, was da wann wie gemacht wird bzw. was da jeweils erfüllt sein muss.
 

Zurück
Oben