`
youlong699
  • 浏览: 22676 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

static static final 与 static 语句块

 
阅读更多

 

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的常量池可以看到

  1. const #5 = String   #23;    //  bluedavy_const 
  2. const #23 = Asciz    bluedavy_const;
bluedavy_const 已经直接搞到了A的常量池里, 脱离了B ;
而对比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加载的。
分享到:
评论

相关推荐

    java中final和static的区别

    8. 静态代码块:静态代码块是在类中独立于类成员的 static 语句块,可以有多个,位置可以随意放,它不在任何的方法体内,JVM 加载类时会执行这些静态代码块,是该类中最先被执行的代码,如果有多个静态代码块,会...

    13_Java面向对象_第5天(static、final、匿名对象、内部类、包、修饰符、代码块)_讲义

    本讲义主要涵盖了Java中的几个核心概念,包括`static`、`final`、匿名对象、内部类、包、修饰符以及代码块。下面将逐一详细阐述这些知识点。 1. **`static`关键字**: `static`关键字在Java中用于声明类级别的变量...

    欧柏泰克:Java包的静态导入import static和import的区别

    静态导入是使用import static语句来实现的,其语法为:import static package.class.*;或者import static package.class.staticMember;其中,package.class是要导入的类,*表示所有静态成员,staticMember是要导入的...

    java static详解.doc

    - 当`static`与`final`一起使用时,创建的是常量。对于变量,这意味着一旦赋值就不能更改,且可通过类名直接访问,如:`ClassName.FINAL_VARIABLE`。 - 对于方法,`static final`表示该方法不能在子类中被覆盖,...

    java中static作用详解

    4. **static与final结合使用**: - `static final`修饰的变量被称为常量,其值在编译时确定并不可改变。这些常量可以通过类名直接访问,例如`ClassName.CONSTANT_NAME`。 - `static final`也可用于修饰方法,表示...

    final关键字的使用

    2. **Return语句与Finally块的关系** 当在一个方法中同时存在`return`语句和`finally`块时,即使`return`语句先被执行,`finally`块中的代码仍然会被执行。这在一定程度上保证了代码的完整性和资源的有效管理。...

    MLDN魔乐JAVA_10static关键字.rar

    在Java 5及以上版本中,你可以使用`static import`语句引入类的静态成员,这样在后续代码中可以直接使用它们,而无需通过类名来引用。例如,`import static java.lang.Math.PI;`后,你就可以直接写`PI`而不是`Math....

    Java基础练习题练习下静态块的用处

    1. **定义**:静态块由`static`关键字修饰,是一组在类中声明的语句,通常包含初始化操作。它的形式如下: ```java public class MyClass { static { // 静态块的代码 } } ``` 2. **执行时机**:静态块在类首次被...

    Java中的静态变量静态方法静态块与静态类.docx

    静态块是在类定义中使用`static`关键字定义的一组语句。当类被加载到内存时,静态块会被执行一次。 - **特点**: - 静态块通常用于初始化类的一些静态资源或配置。 - 类加载后静态块只执行一次,即使类被多次加载...

    Java中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 = ...

    Java中static关键字的作用和用法详细介绍

    当`static`与`final`一起使用时,创建的是常量,这样的变量一旦被赋值后,就不能再改变。例如,`public static final String VERSION = "1.0";` 这样的变量在程序运行期间保持不变,且可以跨类访问,常用于定义常量...

    JAVA100例之实例54 使用语句预处理

    在Java中,虽然没有直接的宏定义,但我们可以使用枚举(enum)和常量(final static)来达到类似的效果。例如,定义一个常量PI: ```java public class Constants { public static final double PI = 3.14159; } `...

    java贪吃蛇实验报告.doc

    final static int nodeHeight = 10; //蛇身的坐标 static int x; static int y; //食物的坐标 static int fx; static int fy; static ArrayList&lt;Node&gt; snakebody;//设置蛇身 static int key ; static int ...

    Java高级工程师岗位笔试题目.docx

    3. Java中,对于try-catch-finally语句块,以下描述正确的是? A. try块是必须的,catch块和finally块是可选的 B. 如果try块中没有抛出异常,则catch块和finally块都不会执行 C. finally块无论是否发生异常都会...

    浅谈Java finally语句到底是在return之前还是之后执行(必看篇)

    从结果可以看到,finally 块中的 return 语句会覆盖 try 块中的 return 语句,try 块中的 return 语句就不能返回了。 finally 语句是在 try 的 return 语句执行之后,return 返回之前执行的。 finally 块中的 ...

    使用SQL语句操作SQLite数据库

    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); } ...

    java 基础之final、finally和finalize的区别

    finally 语句块总是会被执行的,即使 try 或 catch 语句块中有 return 语句。例如: ```java public class FinallyDemo { public static void main(String[] args) { try { System.out.println(1/0); // occurs ...

    qfedu多态 Object,final

    5. **定义常量**:在Java中,通常使用`public static final`修饰符定义常量。这些常量应遵循一定的命名规则,如全大写字母。 ```java public class Constants { public static final int MAX_VALUE = 100; } ``...

Global site tag (gtag.js) - Google Analytics