由 bluedavy 的一篇博客展开
· <clinit>
是由编译器收集static 字段、static 语句块生成的静态初始化方法, 虚拟机在初始化类的时候负责执行,并且父类先于子类;jvm负责加锁同步多个企图并发初始化一个类的调用 。
正是由于这里对<clinit>的隐含加锁,导致了B大帖子里死锁现象的产生。
类的初始化问题可以见《深入jvm虚拟机》 p187
通过javap -c 找不到<clinit> ,但是能看到static{}块,实际上它就是<clint> , 见R大帖子
· static 字段与 static final 字段
前者是类级别的, 后者会被搞到常量池, jvm级别的,因此访问一个类的static final 字段并不会导致该类的加载。
验证方法:
public class A{ public static void main(String[] args){ System.out.println(B.NAME); System.out.println(B.CONST_NAME); } } public class B{ public static String NAME="bluedavy"; public static final String CONST_NAME = "bluedavy_const"; static{ System.out.println("hellojava"); } } javap -verbose A : Compiled from "A.java" public class A extends java.lang.Object SourceFile: "A.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #7.#16; // java/lang/Object."<init>":()V const #2 = Field #17.#18; // java/lang/System.out:Ljava/io/PrintStream; const #3 = Field #19.#20; // B.NAME:Ljava/lang/String; const #4 = Method #21.#22; // java/io/PrintStream.println:(Ljava/lang/String;)V const #5 = String #23; // bluedavy_const const #6 = class #24; // A const #7 = class #25; // java/lang/Object const #8 = Asciz <init>; const #9 = Asciz ()V; const #10 = Asciz Code; const #11 = Asciz LineNumberTable; const #12 = Asciz main; const #13 = Asciz ([Ljava/lang/String;)V; const #14 = Asciz SourceFile; const #15 = Asciz A.java; const #16 = NameAndType #8:#9;// "<init>":()V const #17 = class #26; // java/lang/System const #18 = NameAndType #27:#28;// out:Ljava/io/PrintStream; const #19 = class #29; // B const #20 = NameAndType #30:#31;// NAME:Ljava/lang/String; const #21 = class #32; // java/io/PrintStream const #22 = NameAndType #33:#34;// println:(Ljava/lang/String;)V const #23 = Asciz bluedavy_const; const #24 = Asciz A; const #25 = Asciz java/lang/Object; const #26 = Asciz java/lang/System; const #27 = Asciz out; const #28 = Asciz Ljava/io/PrintStream;; const #29 = Asciz B; const #30 = Asciz NAME; const #31 = Asciz Ljava/lang/String;; const #32 = Asciz java/io/PrintStream; const #33 = Asciz println; const #34 = Asciz (Ljava/lang/String;)V; { public A(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 public static void main(java.lang.String[]); Code: Stack=2, Locals=1, Args_size=1 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: getstatic #3; //Field B.NAME:Ljava/lang/String; 6: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 12: ldc #5; //String bluedavy_const 14: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 17: return LineNumberTable: line 3: 0 line 4: 9 line 5: 17 } javap -verbose B: Compiled from "B.java" public class B extends java.lang.Object SourceFile: "B.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #8.#21; // java/lang/Object."<init>":()V const #2 = String #22; // bluedavy const #3 = Field #7.#23; // B.NAME:Ljava/lang/String; const #4 = Field #24.#25; // java/lang/System.out:Ljava/io/PrintStream; const #5 = String #26; // hellojava const #6 = Method #27.#28; // java/io/PrintStream.println:(Ljava/lang/String;)V const #7 = class #29; // B const #8 = class #30; // java/lang/Object const #9 = Asciz NAME; const #10 = Asciz Ljava/lang/String;; const #11 = Asciz CONST_NAME; const #12 = Asciz ConstantValue; const #13 = String #31; // bluedavy_const const #14 = Asciz <init>; const #15 = Asciz ()V; const #16 = Asciz Code; const #17 = Asciz LineNumberTable; const #18 = Asciz <clinit>; const #19 = Asciz SourceFile; const #20 = Asciz B.java; const #21 = NameAndType #14:#15;// "<init>":()V const #22 = Asciz bluedavy; const #23 = NameAndType #9:#10;// NAME:Ljava/lang/String; const #24 = class #32; // java/lang/System const #25 = NameAndType #33:#34;// out:Ljava/io/PrintStream; const #26 = Asciz hellojava; const #27 = class #35; // java/io/PrintStream const #28 = NameAndType #36:#37;// println:(Ljava/lang/String;)V const #29 = Asciz B; const #30 = Asciz java/lang/Object; const #31 = Asciz bluedavy_const; const #32 = Asciz java/lang/System; const #33 = Asciz out; const #34 = Asciz Ljava/io/PrintStream;; const #35 = Asciz java/io/PrintStream; const #36 = Asciz println; const #37 = Asciz (Ljava/lang/String;)V; { public static java.lang.String NAME; public static final java.lang.String CONST_NAME; Constant value: String bluedavy_const public B(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return LineNumberTable: line 1: 0 static {}; Code: Stack=2, Locals=0, Args_size=0 0: ldc #2; //String bluedavy 2: putstatic #3; //Field NAME:Ljava/lang/String; 5: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream; 8: ldc #5; //String hellojava 10: invokevirtual #6; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 13: return LineNumberTable: line 2: 0 line 5: 5 line 6: 13 }
从A的常量池可以看到
- const #5 = String #23; // bluedavy_const
- const #23 = Asciz bluedavy_const;
而对比A的代码:
3: getstatic #3; //Field B.NAME:Ljava/lang/String;
12: ldc #5; //String bluedavy_const
也可以看到, 使用两个常量的不同
另外,可以在运行代码时加上-verbose:class 打印类加载信息,如果去掉
System.out.println(B.NAME);
仅保留
System.out.println(B.CONST_NAME);
是不会导致B.class加载的。
相关推荐
8. 静态代码块:静态代码块是在类中独立于类成员的 static 语句块,可以有多个,位置可以随意放,它不在任何的方法体内,JVM 加载类时会执行这些静态代码块,是该类中最先被执行的代码,如果有多个静态代码块,会...
本讲义主要涵盖了Java中的几个核心概念,包括`static`、`final`、匿名对象、内部类、包、修饰符以及代码块。下面将逐一详细阐述这些知识点。 1. **`static`关键字**: `static`关键字在Java中用于声明类级别的变量...
静态导入是使用import static语句来实现的,其语法为:import static package.class.*;或者import static package.class.staticMember;其中,package.class是要导入的类,*表示所有静态成员,staticMember是要导入的...
- 当`static`与`final`一起使用时,创建的是常量。对于变量,这意味着一旦赋值就不能更改,且可通过类名直接访问,如:`ClassName.FINAL_VARIABLE`。 - 对于方法,`static final`表示该方法不能在子类中被覆盖,...
4. **static与final结合使用**: - `static final`修饰的变量被称为常量,其值在编译时确定并不可改变。这些常量可以通过类名直接访问,例如`ClassName.CONSTANT_NAME`。 - `static final`也可用于修饰方法,表示...
2. **Return语句与Finally块的关系** 当在一个方法中同时存在`return`语句和`finally`块时,即使`return`语句先被执行,`finally`块中的代码仍然会被执行。这在一定程度上保证了代码的完整性和资源的有效管理。...
在Java 5及以上版本中,你可以使用`static import`语句引入类的静态成员,这样在后续代码中可以直接使用它们,而无需通过类名来引用。例如,`import static java.lang.Math.PI;`后,你就可以直接写`PI`而不是`Math....
1. **定义**:静态块由`static`关键字修饰,是一组在类中声明的语句,通常包含初始化操作。它的形式如下: ```java public class MyClass { static { // 静态块的代码 } } ``` 2. **执行时机**:静态块在类首次被...
静态块是在类定义中使用`static`关键字定义的一组语句。当类被加载到内存时,静态块会被执行一次。 - **特点**: - 静态块通常用于初始化类的一些静态资源或配置。 - 类加载后静态块只执行一次,即使类被多次加载...
4. **static与final结合使用** 当`static`和`final`一起使用时,它们创建的是类级别的常量。这样的变量一旦赋值后就不能改变,且可以在类的任何地方(包括静态上下文)直接访问。例如: ```java public class ...
public static final String DATABASE_NAME = "MyDatabase.db"; public static final String TABLE_NAME = "student_table"; public static final String COL_1 = "ID"; public static final String COL_2 = ...
当`static`与`final`一起使用时,创建的是常量,这样的变量一旦被赋值后,就不能再改变。例如,`public static final String VERSION = "1.0";` 这样的变量在程序运行期间保持不变,且可以跨类访问,常用于定义常量...
在Java中,虽然没有直接的宏定义,但我们可以使用枚举(enum)和常量(final static)来达到类似的效果。例如,定义一个常量PI: ```java public class Constants { public static final double PI = 3.14159; } `...
final static int nodeHeight = 10; //蛇身的坐标 static int x; static int y; //食物的坐标 static int fx; static int fy; static ArrayList<Node> snakebody;//设置蛇身 static int key ; static int ...
3. Java中,对于try-catch-finally语句块,以下描述正确的是? A. try块是必须的,catch块和finally块是可选的 B. 如果try块中没有抛出异常,则catch块和finally块都不会执行 C. finally块无论是否发生异常都会...
从结果可以看到,finally 块中的 return 语句会覆盖 try 块中的 return 语句,try 块中的 return 语句就不能返回了。 finally 语句是在 try 的 return 语句执行之后,return 返回之前执行的。 finally 块中的 ...
private static final String DATABASE_NAME = "test.db"; private static final int DATABASE_VERSION = 1; public DBHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); } ...
finally 语句块总是会被执行的,即使 try 或 catch 语句块中有 return 语句。例如: ```java public class FinallyDemo { public static void main(String[] args) { try { System.out.println(1/0); // occurs ...
5. **定义常量**:在Java中,通常使用`public static final`修饰符定义常量。这些常量应遵循一定的命名规则,如全大写字母。 ```java public class Constants { public static final int MAX_VALUE = 100; } ``...