Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Um zu verfolgen wann eine Klasse geladen wird habe ich ganz oben folgenden code eingefuegt:
static {
System.out.println("Enter XYZClass");
}
Ich uebergebe diese Klasse einer Methode. "Enter XYZClass" wird aber noch nicht ausgedruckt. Was geschieht mit der Klasse an diesem Punkt? Wird nur der Classloader gebeten die Klasse aus dem JAR zu laden? Sonst nichts?
Werden an diesem Punkt bereits Annotationen ausgewertet?
Wann wird eine Klasse tatsaechlich geladen...d.h. komplett interpretiert? Wenn man auf eine Variable zugreift bzw. eine Instanz erstellt?
Das static {...} dient ja eigentlich dazu, statische Felder in einer Klasse zu initialisieren. Das passiert aber erst bevor du ein statisches Feld von irgentwo aufrufst. Wenn du gar kein solches Feld dekladiert hast, wird dein "static-constructur" also niemals aufgerufen.
Das static {...} dient ja eigentlich dazu, statische Felder in einer Klasse zu initialisieren. Das passiert aber erst bevor du ein statisches Feld von irgentwo aufrufst. Wenn du gar kein solches Feld dekladiert hast, wird dein "static-constructur" also niemals aufgerufen.
ich denke auch, beobachtet zu haben, dass die statischen Variablen (auch) bereits beim ersten nicht-statischen Zugriff initialisiert werden,
aber wieso sollte das Beispiel anderenfalls nicht funktionieren?
die Aussage "Das passiert aber erst bevor du ein statisches Feld von irgentwo aufrufst."
würde doch genauso zum ersten Aufruf von fooBar() passen
würde fooBar() nämlich
public void fooBar() {
System.out.println(AndereNochNichtInitialisierteKlasse.bar);
}
lauten, wäre das ganze doch sogar tatsächlich der Fall,
erst beim Aufruf von fooBar() wird AndereNochNichtInitialisierteKlasse initialisiert
...Naja... Laut Tests bewirkt das alleinige Laden noch nicht die Ausführung des "static"-Constructors. Ich kann ein geladenes Class-Objekt in einer Anwendung hin und her schieben, übergeben oder sonstwas. Erst wenn ich einen Member (Konstruktor, Feld, Methode) der Klasse aufrufe oder verwende, wird die Klasse initialisiert. Das initialisieren kann aber auch durch "Class.forName(classname, true, classloader)" forciert werden.
Geladen wird eine Klasse bereits, wenn sie von einer anderen importiert wird, beim Prüfen der Abhängigkeiten oder eben durch Klassen-Lade-Methoden wie oben.
...Naja... Laut Tests bewirkt das alleinige Laden noch nicht die Ausführung des "static"-Constructors. Ich kann ein geladenes Class-Objekt in einer Anwendung hin und her schieben, übergeben oder sonstwas. Erst wenn ich einen Member (Konstruktor, Feld, Methode) der Klasse aufrufe oder verwende, wird die Klasse initialisiert. Das initialisieren kann durch "Class.forName(classname, true, classloader)" forciert werden.
Wie kannst du ein "geladenes Class-Objekt" haben, ohne dass vorher ein Konstruktor oder eine Methode aufgerufen wurde? Zeig mal den Test.
Geladen wird eine Klasse bereits, wenn sie von einer anderen importiert wird, beim Prüfen der Abhängigkeiten oder eben durch Klassen-Lade-Methoden wie oben.
...eine Instanz der Klasse "Class" halt.
2. Zugegeben, das mit der Importanweisung ist nicht wirklich richtig. Im Bytecode tauchen aber statt irgendwelcher Importanweisungen alle verwendeten Klassen namentlich an den Stellen auf, wo sie halt verwendet werden. Die Erklärung mit der Importanweisung fällt nur wesentlich leichter.
@Noctarius: He... Danke... So klingts gut. \/\/
Import existiert zwar im Bytecode nicht mehr, beim Ladeb einer Klasse werden aber trotzdem alle Abhängigkeiten gelinkt und damit der Abhängigkeitenbaum der Klasse aufgebaut. Sprachlich "importiert" (bzw läd) er also schon noch die Klassen zum Linken ;-)
aufrufe...
@Edit: Und wenn ich es mir genau überlege, könnte es beim Laden von Klassen unter Umständen performancemässig ein hübsches Gedrängel geben, wenn sie bei der besagten Abhängigkeitsprüfung gleich initialisiert würden.
Das Laden einer Klasse ist grundsätzlich teuer, daher werden ja auch im Normalfall alle einmal geladenen Klassen vom Classloader gehalten (er darf allerdings nicht mehr genutzte Klassen abräumen um Speicher freizugeben).
Was meinst du mit Initialisieren? Meinst du Instanzieren?
public class K {
public static void main(String[] args) throws Exception {
Class.forName("test.FooBar");
}
}
class FooBar {
static {
System.out.println("foobar");
}
}