class Test {
public static void main(String arg[]) {
System.out.println("**MAIN METHOD");
System.out.println(Mno.VAL); // SOP(9090);
System.out.println(Mno.VAL + 100); // SOP(9190);
}
}
class Mno {
final static int VAL = 9090;
static {
System.out.println("**STATIC BLOCK OF Mno\t: " + VAL);
}
}
Ich weiß, dass ein static
Block ausgeführt wurde, wenn die Klasse geladen wurde. In diesem Fall ist die Instanzvariable innerhalb der Klasse Mno
jedoch so final
, dass der static
Block nicht ausgeführt wird.
Warum ist das so? Und wenn ich das entfernen final
würde, würde es gut funktionieren?
Welcher Speicher wird zuerst zugewiesen, die static final
Variable oder der static
Block?
Wenn final
die Klasse aufgrund des Zugriffsmodifikators nicht geladen wird, wie kann die Variable dann Speicher erhalten?
java
static
access-modifiers
Sthita
quelle
quelle
Antworten:
static final int
Feld ist eine Konstante zur Kompilierungszeit und sein Wert wird ohne Bezugnahme auf seinen Ursprung fest in die Zielklasse codiert.Im Einzelnen entspricht der kompilierte Bytecode dem:
Sobald Sie entfernen
final
, handelt es sich nicht mehr um eine Kompilierungszeitkonstante, und das oben beschriebene spezielle Verhalten gilt nicht mehr. DieMno
Klasse wird wie erwartet geladen und ihr statischer Initialisierer wird ausgeführt.quelle
Der Grund , warum die Klasse nicht geladen ist , dass
VAL
istfinal
und es wird mit initialisiert einen konstanten Ausdruck (9090). Wenn und nur wenn diese beiden Bedingungen erfüllt sind, wird die Konstante zur Kompilierungszeit ausgewertet und bei Bedarf "fest codiert".Um zu verhindern, dass der Ausdruck zur Kompilierungszeit ausgewertet wird (und die JVM Ihre Klasse laden lässt), können Sie entweder:
Entfernen Sie das letzte Schlüsselwort:
oder ändern Sie den Ausdruck auf der rechten Seite in einen nicht konstanten Ausdruck (auch wenn die Variable noch endgültig ist):
quelle
Wenn Sie den generierten Bytecode mit sehen
javap -v Test.class
, wird main () wie folgt ausgegeben:Sie können in "
11: sipush 9090
" deutlich sehen, dass der statische Endwert direkt verwendet wird, da Mno.VAL eine Kompilierungszeitkonstante ist. Daher ist es nicht erforderlich, die Mno-Klasse zu laden. Daher wird der statische Block von Mno nicht ausgeführt.Sie können den statischen Block ausführen, indem Sie Mno wie folgt manuell laden:
quelle
Tatsächlich haben Sie diese Mno-Klasse nicht erweitert, sodass beim Start der Kompilierung eine Konstante der Variablen VAL generiert wird und beim Start der Ausführung, wenn diese Variable benötigt wird, ihre Last aus dem Speicher stammt. Es ist also nicht erforderlich, dass Ihre Klasse referenziert, damit der statische Bock nicht ausgeführt wird.
Wenn die Klasse
A
die Klasse erweitertMno
, wird der statische Block in die Klasse aufgenommen.A
Wenn Sie dies tun, wird dieser statische Block ausgeführt. Beispielsweise..quelle
Soweit ich weiß, wird es in der Reihenfolge seines Auftretens ausgeführt. Zum Beispiel :
wird gedruckt
Ich habe es gerade getestet und die Statik wird initialisiert (=> print), wenn die Klasse "Statique" tatsächlich in einem anderen Code verwendet und "ausgeführt" wird (in meinem Fall habe ich "new Statique ()" ausgeführt.
quelle
Statique
Klasse auf diese Weise ladennew Statique()
. Während der gestellten Frage wird dieMno
Klasse überhaupt nicht geladen.