Referenz auf Klasse als Rückgabewert

iTobi97

Aktives Mitglied
Hallo liebe Community,
ich versuche gerade eine Referenz auf die selbe Klasse als Rückgabewert einer Methode zu verwenden. Diese Methode ist mit Objekten ja relativ einfach:
Code:
public TestKlasse setA(A a) {
this.a = a;
return this;
}
Sodass ich später den Code wie folgt verwenden kann:
Code:
Testklasse testklasse = new Testklasse();
testklasse.setA("abc").setB("bcd").setC("cde"); //usw

Nach dem gleichen Prinzip habe ich das selbe versucht, allerdings mit statischen Methoden (mit welchen ich auch wieder statische Attribute setze):

Code:
public static Class setGUI(GUI gui){
        creationGui = gui;
        return ActionHandler.class;
}

Kann mir jemand kurz sagen, was ich da falsch mache, bzw. wo ich den Logikfehler habe?

Viele Grüße
 
Dein Ansatz:
- Zugriff auf Instanzfelder einer Instanz einer Klasse sollte möglich sein (ist ja auch)
- somit sollten Zugriffe auf statische Felder einer Klasse, also Instanz von java.lang.Class, auch möglich sein (ist es leider nicht, bzw. nur per Reflection)
erscheint zwar nachvollziehbar als logisch, funktioniert aber in Java leider nicht.
Das liegt daran, dass zwar ein Objekt eine Instanz einer Klasse etwa "Testklasse" ist, aber eine Klasse selbst nur zum Zwecke der Laufzeit-Reflection eine Instanz der allgemeinen java.lang.Class Klasse ist.
Wenn du also java.lang.Class zurücklieferst, weiß der Compiler leider nicht mehr, was das statisch für eine Klasse war und welche Felder sie hatte, um dann darauf zuzugreifen.
Das heißt, der Ausdruck ActionHandler.someStaticField ist zwar gültig, aber nicht ((Class)theActionHandlerClass).someStaticField. Auch nicht, wenn du z.B. Generics verwendest, um dem Compiler zu sagen, dass die Class eigentlich eine Class<ActionHandler> war.
Und der Grund ist, dass hier eine gewisse Mehrdeutigkeit vorliegt: Java weiß hier nicht, ob du nun eigentlich auf ein statisches Feld der gemeinten Klasse (also dem Laufzeittyp des zugegriffenen Class-Objektes) zugreifen möchtest, oder aber, ob du auf ein "Instanzfeld" oder Methode des java.lang.Class Objektes selbst (was ja Teil der Reflection API ist) zugreifen wolltest.
Java nimmt hier das letztere an, und du kannst z.B. ((Class)theActionHandlerClass).getField("someStaticField").get(null) machen, um lesend auf das Feld "someStaticField" zuzugreifen.
Also, in Java bzw. der JVM müssen Zugriffe auf statische Klassenfelder immer mit dem ganz konkreten Klassentyp angegeben werden und nicht mit dem "Laufzeittyp" einer Variablen vom Typ java.lang.Class. Oder du greifst per Java Reflection API auf die Felder zu.
 
Oder mit anderen Worten:
Es gibt den konzeptuellen Unterschied zwischen:
Java:
someExpression.a()
und:
Java:
SomeClass.a()
Im ersteren Fall findet ein virtueller (dynamic dispatch) Aufruf der Methode `a` auf dem Laufzeittyp des Objektes, welcher das Ergebnis des Ausdrucks `someExpression` ist, statt. a selbst muss hierbei natürlich auch auf dem statischen Typ des Ausdrucks existieren.
Im zweiten Fall sieht der Java Compiler, dass hier ganz explizit eine bekannte Klasse gemeint ist und es findet stattdessen ein statischer Methodenaufruf auf die statische Methode a() deklariert in SomeClass (oder Superklasse) statt.
Dein Fall mit dem Zurückgeben einer Instanz von java.lang.Class und dann Zugriff darauf ist der erstere Fall:
Java:
class SomeClass {
  static void a() {
    System.out.println("Hello!");
  }
}
Class giveClass() {
  return SomeClass.class;
}
void test() {
  Class clazz = giveClass();
  clazz.a(); // <- COMPILER ERROR! 'a' ist unbekannt.
}
Hier wird der Zugriff auf 'a' abgewiesen, da java.lang.Class keine solche Instanzmethode bereitstellt.
 
Wenn sowas nötig ist, ist es meistens sowieso schlechter Stil und wird besser anders gelöst 😉


Man kann aber "hacky" sein, und als Rückgabetyp den entsprechenden Typ angeben und null zurückgeben - darauf kann man dann die statischen Methode aufrufen - ist aber wirklich ein ziemlicher Hack...
 
@httpdigest Vielen Dank für die ausführliche Antwort. Ich hab irgendwie schon befürchtet, dass die Antwort nicht die einfachste ist. Ich habe bereits vermutet, dass man versuchen könnte, das Problem mit Reflections anzugehen.

@mrBrown Ich stimme dir völlig zu, dass das keine schöne Lösung ist, und eigentlich ziemlich schlechter Stil ist. Allerdings habe ich bis jetzt in meinem Code noch keine bessere Lösung gefunden.
In JavaFX hängt ja leider ziemlich viel von der Reihenfolge der Aufrufe und Deklarationen ab, und wenn das Eine Objekt das Andere im Konstruktor benötigt, und Das andere wiederum das Erste, hat man ein Problem 😉
 
Allerdings habe ich bis jetzt in meinem Code noch keine bessere Lösung gefunden.
In JavaFX hängt ja leider ziemlich viel von der Reihenfolge der Aufrufe und Deklarationen ab, und wenn das Eine Objekt das Andere im Konstruktor benötigt, und Das andere wiederum das Erste, hat man ein Problem 😉
Das ist aber nichts, wo man static einsetzen sollte, das macht es nur schlimmer 😉
JavaFX ist da jetzt auch nicht wirklich besonders? Wenn man solche zyklische Abhängigkeiten hat, hat man immer ein Problem, aber Wege ohne static gibt es trotzdem


Wenn du mal Code zeigst, kann man dir da sicher helfen 😉
 
@mrBrown Natürlich sind diese Fragen immer mit dem Code einfacher zu beantworten.
Allerdings darf ich das leider hier nicht machen, da viele Fragen im Zusammenhang mit meinem Studium auftreten, und wir aus urheberrechtlichen Gründen den Code nicht online zeigen dürfen. Daher muss ich die Fragen immer etwas umständlich umschreiben 🙂
 

Zurück
Oben