`
xm_king
  • 浏览: 392680 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
Group-logo
Spring技术内幕读书笔...
浏览量:15374
社区版块
存档分类
最新评论

Static和Final的深度理解

    博客分类:
  • JAVA
阅读更多

      在Java中,static和final是使用频率非常高的关键字,之前也简单地用过static和final,但是始终觉得没有从深层次上理解这两个关键字。本文将从class文件和类的初始化机制出发理解这两个关键字。

一、编译时常量:

     很多人包括我最开始有这种误解,是不是被final修饰的变量就是编译时常量呢,非也。顾名思义,编译时常量是指变量在编译期间就可以确定了,下面我举两个例子说明一下什么是编译时常量。

public class Test{
	public final int  a=100;
}

 看一下,编译之后的class文件:

      此时,变量a是编译时常量,在构造方法中,对变量a分配内存空间之后,将常量111赋值给a。

public class Test{
	public final int  a;
	public Test(int a){
		this.a=a;
	}
}

  编译之后的class文件如下:

      此时,变量a在编译时期并不知道要赋什么值,只有在运行期间实例化Test对象时,去调用构造方法的时候才能知道a的值。这时候a就不是编译时常量。

二、static变量

      static修饰的变量为类(静态)变量,static成员变量是对于整个类而不是类实例而存在的。一个static变量对于每个类来说都只有一份存储空间。而非static变量(实例变量)对于每个对象都有一份存储空间。

       在我们实例化一个Java对象之前,这个对象的类型信息必须已经存放在了Java虚拟机的方法区。Java虚拟机通过装载、连接和初始化一个Java类型,使该类型可以被正在运行的Java程序所使用。其中装载就是把二进制的class文件读入Java虚拟机中;而连接就是把这种已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时数据区中,连接分为三个子步骤:验证、准备和解析。验证工作是确认class文件符合Java语言的语义规范。在准备阶段,Java虚拟机为类变量分配内存,设置默认初始值。解析过程是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用。最后一个步骤就是初始化,也就是为类变量赋予正确的初始值。

     下面我们来看一下类(静态)变量的初始化过程。

      所有的类变量初始化语句和类型的静态初始化器都被Java编译器收集在一起,放到一个特殊的方法。在class文件中,这个方法被称为"<clinit>"。通常的java程序时无法调用这个<clinit>方法。这个方法只能被java虚拟机调用,专门用把类型的静态变量设置为它们的正确初始值。以下两种方式产生的字节码文件时相同的。

public class Test{
	public static int  a=111;
}
public class Test{
	public static int a;
	static{
		a=111;
	}
}

      并非所有的类都在class文件中拥有一个<clinit>()方法。如果类没有声明任何类变量,也没有静态初始化语句,那么它就不会有<clinit>()方法。若果类声明了类变量,但是没有明确使用类变量初始化语句或者静态初始化语句初始化它们,那么类不会有<clinit>()方法。如果类仅包含静态final变量的类变量初始化语句,而且这些类变量初始化语句采用编译时常量表达式,类也不会有<clinit>()方法。在编译的时候,java编译器把编译时常量(用final声明以及编译时已知的值初始化的类变量)则和一般的类变量的处理方式不同,每个使用编译时常量的类型都会复制它的所有常量到自己的常量池中,或嵌入到它的字节码中。也就是Java虚拟机会将常量直接保存到类文件中。

public class Test{
	public static final int a=11;
	
}

 

3
0
分享到:
评论
3 楼 Mr_lee_2012 2012-08-26  
来过,写的不错。
2 楼 zuchunlei2010 2011-09-17  
写的很好,看的很明白。
1 楼 337240552 2011-07-25  
写的很好

相关推荐

    Thinking in Java 中文第四版+习题答案

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    Think in Java(中文版)chm格式

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer...

    JAVA_Thinking in Java

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    Java初学者入门教学

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    ThinkInJava

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    java 编程入门思考

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    thinkinjava

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    java联想(中文)

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    Thinking in Java简体中文(全)

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    Thinking in Java(中文版 由yyc,spirit整理).chm

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    JAVA_Thinking in Java(中文版 由yyc,spirit整理).chm

    12.2.9 使克隆具有更大的深度 12.2.10 为什么有这个奇怪的设计 12.3 克隆的控制 12.3.1 副本构建器 12.4 只读类 12.4.1 创建只读类 12.4.2 “一成不变”的弊端 12.4.3 不变字串 12.4.4 String和StringBuffer类 12.4....

    二十三种设计模式【PDF版】

    为能和大家能共同探讨"设计模式",我将自己在学习中的心得写下来,只是想帮助更多人更容易理解 GoF 的《设计模式》。由 于原著都是以C++为例, 以Java为例的设计模式基本又都以图形应用为例,而我们更关心Java在中间件等...

    Java 语言基础 —— 非常符合中国人习惯的Java基础教程手册

     final 说明一个类为最终类,即改类不能再有子类。  public 说明类为公共类,该类可以被当前包以外的类和对象使用。  private 说明类为私有类。 (4) extends 子句用于说明类的直接超类。 (5) implements ...

    (全)传智播客PHP就业班视频完整课程

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全韩顺平传智播客PHP就业班视频,10月份全集

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    韩顺平PHP JS JQUERY 所有视频下载种子 货真价实

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全传智播客PHP就业班视频课,8月份视频

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

    史上最全韩顺平传智播客PHP就业班视频,9月份全集

    继承与实现比较 final const 9-9 6.面向对象编程综合练习 10-10 1 课程回顾 10-10 2 正则表达式 10-10 3 正则表达式 子表达式 引用 反向捕获 10-10 4 正则表达式 元字符 语法 10-10 5 元字符 实例应用 10-10 6 供求...

Global site tag (gtag.js) - Google Analytics