类的初始化由执行类中静态代码块的初始化和类中声明的静态域的初始化两部分组成

接口的初始化由接口中声明的域(常量)的初始化组成

初始化的时机

类或接口T在以下任意情况发生之前会立即进行初始化:T是一个类并且创建了一个T的实列

T中声明的一个静态方法被调用

T中声明的一个静态域被分配(assigned)

T中的一个静态域被使用并且该域不是一个常量变量(constant variable)

当一个类被初始化时,它的超类也会被初始化(如果之前未被初始化的话),以及声明任何默认方法的父接口也会被初始化(如果之前未被初始化);接口自身的初始化并不会导致其父接口的初始化

引用一个静态域(static field)只会导致实际声明该域的类进行初始化,尽管它可能通过子类名、子接口、或者实现接口的某个类名进行引用。

调用Class类或包java.lang.reflect中的某些方法也会导致类或接口进行初始化(Class.forName).

对于上面4种情况,我们可以举例来验证一下.下面Hello这个类声明了一个常量A,常量变量B(具体什么是常量变量可以参考《java language specification》第4.12.4节),一个静态变量c,以及两个静态代码块(23-30行)1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26public class{

public static final int A = initA();

public static final int B = 10;

public static int c;

static {

System.out.println("Hello静态代码块加载了1.........");

}

/**静态代码块2*/

static {

System.out.println("Hello静态代码块加载了2.........");

}

public (){

System.out.println("Hello构造函数初始化了........");

}

public static void hello(){

System.out.println("Hello.hello方法被调用了........");

}

public static int initA(){

System.out.println("Hello.initA方法被调用了........");

return 10;

}

}

接着,我们写测试类来依次验证上述4种情况.1

2

3

4

5/**测试Hello实例化*/

public void testInstance(){

new Hello();

}

可以在控制面板看到如下输出:Hello.initA方法被调用了……..

Hello静态代码块加载了1………

Hello静态代码块加载了2………

Hello构造函数初始化了……..

从输出中我们可以看到Hello类确实在实例化之前被初始化了,同时因为Hello是一个类,它的初始化包括静态代码块的执行和静态域的初始化两部分,这点从输出中也可以得到印证。首先第一行输出证明初始化了静态域A(接着是B,c这里没法从输出中直观的验证);接着第2,3行输出证明初始化执行了静态代码块1和2(静态域或静态代码块的执行顺序和声明顺序有关);最后一行表明Hello的构造函数被调用。2.测试静态方法的调用1

2

3

4

5/** 测试调用Hello的静态方法*/

public void testStaticMethodInvoke(){

Hello.hello();

}

控制面板输出:Hello.initA方法被调用了……..

Hello静态代码块加载了1………

Hello静态代码块加载了2………

Hello.hello方法被调用了……..

这里我们调用了Hello类中的静态方法getA,同理可以看到类A首先进行了初始化。3.测试静态域被分配(即赋值)1

2

3

4

5/**测试静态域被赋值*/

@Test

public void testStaticFieldAssigned(){

Hello.c = 20;

}

控制面板输出:Hello.initA方法被调用了……..

Hello静态代码块加载了1………

Hello静态代码块加载了2………

同理可以得出静态域被分配(赋值)也会触发初始化操作4.测试使用类的常量

我们首先测试使用常量A

1

2

3

4

5

6/**测试调用Hello的常量A*/

@Test

public void testConstantA(){

int a = Hello.A;

System.out.println("a=" + a);

}

控制面板输出:Hello.initA方法被调用了……..

Hello静态代码块加载了1………

Hello静态代码块加载了2………

a=10

可以看到调用常量A触发了类Hello的初始化动作.

再来测试使用常量B:

1

2

3

4

5

6/**测试调用Hello的常量B*/

@Test

public void testConstantVariableB(){

int b = Hello.B;

System.out.println("b=" + b);

}

控制面板输出:b=10

会奇怪的发现控制面板只输出了b=10,而没有其他信息。也就是说使用Hello.B并没有触发Hello类的初始化动作;

这是为什么呢?

我们再次看第4种情况T中的一个静态域被使用并且该域不是一个常量变量(constant variable),T中一个静态域被使用也会触发类的初始化操作,但是有一个前提是该静态域必须不是一个常量变量.对于常量变量的定义可以详见java语言规范中第4.12.4节的定义,这里先简单说明一下,对于类中的用final static声明的常量字段,如果直接使用基本类型或string类型的字面量表达式直接赋了值,那么就可以认为该字段是一个常量变量.因此Hello类中的静态字段B是一个常量变量,使用它不会触发Hello类的初始化操作.5.最后测试一下如果几种情况同时出现1

2

3

4

5

6

7

8/** 测试所有情况*/

@Test

public void testAll(){

new Hello();

Hello.hello();

System.out.println("Hello.A=" + Hello.A);

System.out.println("Hello.B=" + Hello.B);

}

控制面板输出:

可以看到,类Hello只会被初始化一次。

java 接口初始化_Java类和接口的初始化相关推荐

  1. IEnumeratorTItem和IEnumerator Java 抽象类和普通类、接口的区别——看完你就顿悟了...

    IEnumerable 其原型至少可以说有15年历史,或者更长,它是通过 IEnumerator 来定义的,而后者中使用装箱的 object 方式来定义,也就是弱类型的.弱类型不但会有性能问题,最主要 ...

  2. Java泛型教程–示例类,接口,方法,通配符等

    泛型是Java编程的核心功能之一,它是Java 5中引入的.如果您使用的是Java Collections ,并且版本5或更高版本,则可以肯定使用了它. 在集合类中使用泛型非常容易,但是它提供了比仅创 ...

  3. jdbc是java语言编写的类和接口_JDBC——Java语言连接数据库的标准

    JDBC概述 API JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Jav ...

  4. java类编来那个初始化顺序_Java类及对象的初始化顺序

    1.初始化规则: 下面规则优先级从前往后依次降低 ①.加载一个类时先加载初始化基类后加载初始化扩展类: ②.类的初始化高于实例的初始化: 类的初始化依靠(静态代码块static{....})以及(静态 ...

  5. java 接口初始化_Java类的初始化 | 学步园

    类的初始化时机1.创建类的实例 2.访问类或接口的静态变量(static final常量除外,static final变量可以)3.调用类的静态方法 4.反射(Class.forName(packag ...

  6. java接口常用_java的常用接口

    Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements). 所有实现Collection接口的类 ...

  7. java中塑形_Java学习5——接口和多态

    1 接口 接口相当于一个完全抽象的,没有任何实现的类 所有的成员函数都是抽象函数 所有的成员变量都是public static final而且一定要赋予初值 接口中的静态函数必须有函数体 接口在声明时 ...

  8. java 类 加载 初始化_java类的加载与初始化

    https://blog.csdn.net/u013349237/article/details/71076617 1在命令行启动虚拟机jvm进行加载, 2用class.forname()方法进行动态 ...

  9. java的连接 初始化_java类从加载、连接到初始化过程详解

    Java代码在编译后会转化成Java字节码,字节码被类加载器加载到JVM里,JVM执行字节码,最终需要转化成汇编指令在CPU上执行,Java中所使用的并发机制依赖于JVM的实现和CPU的指令. 类加载 ...

最新文章

  1. 下拉列表控制文本框的个数思路
  2. 微信小程序服务器开小差了,微信小程序wx.request请求封装
  3. ddd模型的pom版本怎么管理_DDD 中的那些模式 — CQRS
  4. java调python画图_Python Matplotlib plot 绘图
  5. AliOS Things v1.1.2新特性
  6. HTMLElement对象
  7. [leetcode]1375. 灯泡切换器III
  8. Sketch 51 for Mac(矢量绘图软件)汉化激活版
  9. 从一名开发人员转做测试的一些感悟
  10. Android模仿新浪微博(启动界面登陆界面)
  11. 有没有测试牙齿需不需要修正的软件,三分钟教你测试自己的牙齿需不需要矫正!...
  12. Gluster相关命令
  13. 老程序员教你如何提高开发效率、成为大神1——人文思维进化与信众
  14. mysql 锁定表_mysql表锁定技术
  15. 跨跃平台交流无极限——linux下如何使用即时聊天工具,跨跃平台 交流无极限——Linux下如何使用即时聊天工具(一)...
  16. python str和repr的区别_python的str()和repr()的区别
  17. java中的集合详解
  18. Excel小技巧----VLOOKUP数据匹配
  19. 圣经书||《强化学习导论(2nd)》原书、代码、习题答案、课程视频大全
  20. Microsoft Corporation 去掉 windows 修改 启动加载 版权

热门文章

  1. APP推广小窍门:三大法宝让你吸引5000万用户
  2. 单目标跟踪--KCF算法(核化相关滤波算法)Python实现(超详细)
  3. python frozenset_Python中set与frozenset方法和区别详解
  4. 提取深度网络某一层特征
  5. 四、SOCKET 协议
  6. Python-100-Days之 数据分析 Day67 番剧数据可视化
  7. element-plus 组件解析 - Collapse 折叠面板
  8. python 将三维数据转为二维_Python二维数组与三维数组切片详解
  9. MySQL数据库索引组合索引的最左优先原则
  10. 远程FPGA虚拟实验平台之计数器与分频器(10Mhz分为1hz verilog HDL描述)