在 Java 里定义一个类的时候,很多时候我们需要提供成员变量,成员变量专业叫法是 Memeber Variable 或者干脆的叫作 Field. 根据是否使用 static 关键字修饰,可以将 Field 分为两种:

static field:也称作 class variable,这种 filed 属于 class,并不属于单个 instance,所有该 class 的 intance 共享内存中的同一份 class field。

non-static field:也称作 instance variable,它属于每一个具体的 instance,class 的每一个 instance 独享一份 non-static field。

接下来进入本文的主题:java 中 field 的初始化方式。

从初始化代码所在的位置看,可以粗略的分为三种:

在声明 field 的地方进行初始化。

在类的构造方法(constructor) 里对 field 进行初始化

在初始化块(initialization block) 中对已声明的 field 进行初始化

第一种方式主要用于简单的赋值,使用这种方式的前提是作为初始化变量的值是已知的并且通常可以使用单行的赋值语句完成(例外?参见 Double Brace Initialization)。

public class Foo {

// class variable initializer

private static Logger logger = LoggerFactory.getLogger(Foo.class);

// instance variable initializer

private List fooList = new ArrayList();

}

对于复杂的初始化语句,如包含异常处理(try-catch)、使用循环结构初始化等,则需要考虑另外两种初始化方式:constructor 和 initialization block。其中 initialization block 根据是否由 static 关键字修饰,又可分为 static(class) initialization block 和 instance(object) initialization block,前一种只能初始化 class variable,用它进行 instance variable 的初始化会导致编译错误。

构造方法(constructor)可以用于初始化 instance variable。除此之外,少数情况下,instance variable 的初始化需要考虑使用 instance initialization block 完成。例如,在匿名类中的初始化(因匿名类无构造方法),或者类中包含了多个 constructor,而它们有公共的一些复杂初始化操作,此时可以考虑将这些操作提取到 instance initialization block 里。除了这两种情况,在你的代码中应该尽量少使用 instance initialization block。

static initialization block 用于处理带有 class variable 的初始化操作。

public class BarClass {

private static Properties propTable;

static {

try {

propTable.load(new FileInputStream("/data/user.prop"));

} catch (Exception e) {

propTable.put("user", System.getProperty("user"));

propTable.put("password", System.getProperty("password"));

}

}

}

static initialization block  的另一个功能与线程安全(thread safe)相关。JVM 保证使用同一个 ClassLoader 加载的类中的 static initialization block 只被执行一次,因而它是线程安全的。也正因为这一点,很多时候我们可以利用 static initialization block 执行一些初始化(write)操作,而无需对该 block 使用任何同步机制。

最后来看一下初始化代码的执行顺序问题。在此之前,先看下面这段代码,它可以完整执行,请试着分析一下最后的输出是什么。

/**

* @author wxl24life

*

*/

public class ClassInitializerOrderTest{

public static void main(String[] args) {

B a = new B();

}

}

class A {

static int a = initA();

static int initA() {

System.out.println("call 1");

return 0;

}

{

System.out.println("call 5");

}

{

System.out.println("call 6");

}

static {

System.out.println("call 2");

}

static {

System.out.println("call 3");

}

static int b = initB();

static int initB() {

System.out.println("call 4");

return 0;

}

A() {

System.out.println("call 7");

}

}

class B extends A {

{

System.out.println("call 8");

}

String str = initStr();

String initStr() {

System.out.println("call 9");

return "call 8";

}

static {

System.out.println("call 10");

}

B() {

super();

System.out.println("call 12");

}

{

System.out.println("call 11");

}

}

用几句话概括下初始化顺序规则(假设调用方式类似于上面代码,即使用 new 操作符 ):

static 先于 non-static, non-static 先于 constructor。这里的 static 统指 static field 和 static initialization block 两种初始化方式,non-static 同上。

static 初始化代码按照在源代码中定义的顺序从上往下以此执行,non-static 同上。

存在继承关系时,优先执行基类中的初始化语句。

执行顺序测试代码的输出结果:

call 1

call 2

call 3

call 4

call 10

call 5

call 6

call 7

call 8

call 9

call 11

call 12

参考阅读:

java类成员变量初始化_探讨Java类中成员变量的初始化方式相关推荐

  1. java中变量 关键字_基于java的voliate关键字详解

    voliate关键字的作用: 一.内存可见性 基于缓存一致性协议,当用voliate关键字修饰的变量改动时,cpu会通知其他线程,缓存已被修改,需要更新缓存.这样每个线程都能获取到最新的变量值. 二. ...

  2. java 传绝对路径无效_【Java并发005】原理层面:volatile关键字全解析

    一.前言 在Java 5之前,volatile是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果. 在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽 ...

  3. 【源码+图片素材】Java王者荣耀游戏开发_开发Java游戏项目【王者荣耀】1天搞定!!!腾讯游戏_Java课程设计_Java实战项目_Java初级项目

    王者荣耀是当下热门手游之一,小伙伴们是否想过如何制作一款属于自己的王者荣耀游戏呢? 本课程讲解了一个王者荣耀游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE ...

  4. java 成员变量 成员方法_《Java基础知识》Java成员变量,成员方法,构造方法和析构方法...

    一 成员变量 成员变量是指类的一些属性定义,标志类的静态特征,它的基本格式如下: [访问修饰符][修饰符][类型][属性名称]= [初始值] 访问修饰符:public(公共的):protected(受 ...

  5. java编程思想 初始化_《java编程思想》_第五章_初始化与清理

    初始化和清理是涉及安全的两个问题,java中采用了构造器,并额外提供了"垃圾回收器",对于不再使用的内存资源,垃圾回收器能自动将其释放. 一.用构造器确保初始化 java中,通过提 ...

  6. java中的成员变量和局部变量的区别_java中成员变量与局部变量区别分析

    本文实例分析了java中成员变量与局部变量区别.分享给大家供大家参考.具体分析如下: 成员变量:在这个类里定义的私有变量,属于这个类. 创建以及使用成员变量 public class Person { ...

  7. java 基本类型 不赋值_探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值...

    探究Java中基本类型和部分包装类在声明变量时不赋值的情况下java给他们的默认赋值 当基本数据类型作为普通变量(八大基本类型: byte,char,boolean,short,int,long,fl ...

  8. java全局变量初始化_为什么 Java 中全局变量不一定初始化,局部变量必须初始化?...

    前几天,有个大佬考了我一个问题:为什么类的成员变量不需要指定值就可以自动赋予初始值,而方法内的局部变量就必须指定初始值呢? 说实话,这个问题确实难倒我了,之后我在网上一顿操作,终于把这个问题弄得稍微明 ...

  9. 学java要背的单词_学习JAVA必背的8类常用单词

    Java常用的词还是挺多的,初学者有空多看看,对快速入门Java编程还是有益的.本文沈阳达内IT培训为大家介绍学习JAVA必背的8类常用单词. 1.保留关键字(2个) const --常量,常数:用于 ...

最新文章

  1. 密码学研究-数字签名
  2. 【学习笔记】mysql多实例安装
  3. Java并发编程:深入剖析ThreadLocal
  4. js/jq判断鼠标滚轮方向
  5. 《研磨设计模式》chap22 装饰模式Decorator(2)应用到场景
  6. 详解虚拟机中为Linux添加硬盘
  7. sqlite3数据库使用
  8. 如何妥善处理WebBrowser对Javascript的错误问题,阻止JS弹出框,提高用户体验(原创)...
  9. win2008MySQL双主_MySQL双主配置
  10. logstash filter 处理json数据按原始数据字段数据存储
  11. 场景欺诈的策略梳理、总结与实操
  12. Top1方案源码和数据,腾讯广告受众基础属性预估
  13. 工作中一些环境问题解决记录
  14. 品质管控计划ppt怎样写_供应商质量管理工作计划.ppt
  15. 北京邮电大学计算机专业考研复试经验分享
  16. 【VBox】解决复制VBox虚拟机后提示硬盘UUID 已经存在的问题
  17. Microsoft Office SharePoint Server 2007案例实战开发
  18. mac Segmentation Fault
  19. 北京农学院计算机调剂,2020北京农学院植物科学技术学院招收硕士研究生调剂...
  20. CentOS 6.5 ZIP、RAR文件压缩解压操作详解

热门文章

  1. 解决win10下,excel打不开的问题
  2. html表格边框样式
  3. SWERC13 Decoding the Hallway
  4. Tesseract .Net SDK C# OCR 2022.1
  5. win10 edge浏览器的收藏夹如何在新标签页中打开?
  6. 066-JAVA项目实训:仿QQ即时通讯软件系列讲座一(需求分析)
  7. 超级终端与串口调试助手
  8. 深入学习Linux摄像头(三)虚拟摄像头驱动分析
  9. WE CAN人在行动之——黄晓蓉逛上海 第四集
  10. A Systematic Evaluation of Transient Execution Attacks and Defenses (对暂态执行的攻击和防御的系统评估)(前四节)