Java中的静态块未执行
我知道加载类时会执行Java中的静态块未执行,java,static,access-modifiers,Java,Static,Access Modifiers,我知道加载类时会执行静态块。但是在这种情况下,类Mno中的实例变量是final,因为静态块没有执行 为什么会这样?如果我删除最终版,它会正常工作吗 将首先分配哪个内存,static final变量或static块 如果由于finalaccess修饰符,类没有被加载,那么变量如何获得内存 静态final int字段是一个编译时常量,它的值被硬编码到目标类中,而不引用它的原点 因此,主类不会触发包含该字段的类的加载 因此,不会执行该类中的静态初始值设定项 具体而言,编译的字节码对应于: class
静态
块。但是在这种情况下,类Mno
中的实例变量是final
,因为静态
块没有执行
为什么会这样?如果我删除最终版
,它会正常工作吗
将首先分配哪个内存,static final
变量或static
块
如果由于final
access修饰符,类没有被加载,那么变量如何获得内存
静态final int
字段是一个编译时常量,它的值被硬编码到目标类中,而不引用它的原点李>
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);
}
}
一旦删除
final
,它就不再是编译时常量,并且上面描述的特殊行为不适用。Mno
类按预期加载,并执行其静态初始值设定项。据我所知,它将按外观顺序执行。例如:
public static void main(String arg[]){
System.out.println("**MAIN METHOD");
System.out.println(9090)
System.out.println(9190)
}
将打印
public class Statique {
public static final String value1 = init1();
static {
System.out.println("trace middle");
}
public static final String value2 = init2();
public static String init1() {
System.out.println("trace init1");
return "1";
}
public static String init2() {
System.out.println("trace init2");
return "2";
}
}
我刚刚测试了它,当类“Statique”实际使用并在另一段代码中“执行”时,静态被初始化(=>print)(我的例子是“new Statique()”)未加载该类的原因是
VAL
是final
并且它是用(9090)初始化的。如果且仅当满足这两个条件时,将在编译时计算该常数,并在需要时进行“硬编码”
要防止在编译时对表达式求值(并使JVM加载您的类),您可以:
- 删除最后一个关键字:
trace init1 trace middle trace init2
- 或者将右侧表达式更改为非常量(即使变量仍然是final):
javap-v Test.class生成的字节码,main()的结果如下所示:
final static int VAL = getInt(); //not a constant expression any more
static int getInt() { return 9090; }
您可以在“11:sipush 9090
”中清楚地看到,直接使用了静态终值,因为Mno.VAL是编译时常量。因此不需要加载Mno类。因此不会执行Mno的静态块
您可以通过手动加载Mno来执行静态块,如下所示:
public static void main(java.lang.String[]) throws java.lang.Exception;
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String **MAIN METHOD
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
11: sipush 9090
14: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
17: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
20: sipush 9190
23: invokevirtual #5 // Method java/io/PrintStream.println:(I)V
26: return
实际上,您还没有扩展该Mno类,所以当编译开始时,它将生成变量VAL的常量,当执行开始时,当需要该变量时,它将从内存加载。因此,不需要您的类引用,以便不执行静态块
如果类A
扩展类Mno
,则静态块包含在类A
中。如果执行此操作,则执行该静态块。
例如
class Test{
public static void main(String arg[]) throws Exception {
System.out.println("**MAIN METHOD");
Class.forName("Mno"); // Load Mno
System.out.println(Mno.VAL);
System.out.println(Mno.VAL+100);
}
}
class Mno{
final static int VAL=9090;
static{
System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
}
}
您得到的确切错误和消息是什么?@Patashu,没有错误,这是一个疑问,但是,在不加载类的情况下,如何计算类中最后一个变量的值呢?所有计算都在编译时进行,最终结果都硬编码到引用该变量的所有位置。因此,如果不是原始变量,而是如果是某个对象,那么这种硬编码是不可能的。不是吗?那么,在这种情况下,会加载该类并执行静态块吗?Marko,Sumit的怀疑是正确的,如果不是原语,而是某个对象,那么这种硬编码是不可能的。是吗?那么,在这种情况下,会加载该类并执行静态块吗已执行?@SumitDesai完全正确,这仅适用于基本值和字符串文字。有关详细信息,请阅读您获得此输出的原因,因为您正在通过执行new Statique()加载Statique
类
。在提问时,Mno
类根本没有加载。@fabyn,如果我在测试类中创建Mno对象,如下所示:Mno anc=New Mno();那么很好,但是当前的场景我没有这样做,我的疑问是如果我删除final,那么静态块会很好地执行,否则它不会执行,为什么会这样?是的,下面的答案是完美的。在Main.class的字节码中(使用Mno.VAL),9090是硬编码的。删除final,编译,然后使用javap Main,您将看到getstatic#16;//Field Statique.VAL:I。放回final,编译,然后使用javap Main,您将看到sipush 9090。因为它是在Main.class中硬编码的,所以没有理由加载类MNO,因此没有静态初始化。这回答了第二个问题:“将首先分配哪个内存,静态最终变量还是静态块?”(词汇顺序)
class Test{
public static void main(String arg[]) throws Exception {
System.out.println("**MAIN METHOD");
Class.forName("Mno"); // Load Mno
System.out.println(Mno.VAL);
System.out.println(Mno.VAL+100);
}
}
class Mno{
final static int VAL=9090;
static{
System.out.println("**STATIC BLOCK OF Mno\t:"+VAL);
}
}
public class A extends Mno {
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);
}
}