背景

接口与类真正有所区别的是前面讲述的四种“有且仅有”需要开始初始化场景中的第三种:当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候(如引用接口中定义的常量)才会初始化。 ——《深入理解Java虚拟机:JVM高级特性与最佳实践》

这里讲到引用接口中定义的常量会初始化接口,但是书中也写到引用类中的常量不会导致类被初始化,因为编译阶段已经将常量移动到常量池中了,两者的说法有一些矛盾让我很困惑。

public class InterfaceInitTest {

    public static void main(String[] args) {
System.out.println(Interface.CONSTANT_INT);
} } interface Interface { int CONSTANT_INT = 1; Object CONSTANT_OBJECT = new Object(); Object CONSTANT_OBJECT2 = new Object() {
{
System.out.println("interface init");
}
}; }

1

Process finished with exit code 0

可以看到没有接口并没有被初始化,这和我理解的是一样的,引用类中的常量不会导致类被初始化,引用接口中的常量也不会被初始化。

但是稍微修改一下main函数的代码

public class InterfaceInitTest {

    public static void main(String[] args) {
System.out.println(Interface.CONSTANT_OBJECT);
} }

interface init

java.lang.Object@14ae5a5

Process finished with exit code 0

可以看到同样是引用接口中的常量,有时候接口又会被初始化。

通过在网上找到的一篇文章ConstantValue属性,里面提到常量池中只能引用到基本类型和String类型的字面量。这也就解答了我的困惑:类和接口在被引用常量的时候是否被初始化,取决于这个常量能够在编译时被放进常量池中(排除不支持的类型和运行时常量)。

接口初始化的规则

通过测试发现,以下几种情况接口会被初始化:

  1. 调用接口中不在常量池中的常量(对static字段的引用引发的初始化只会初始化实际定义的接口(尽管可以通过实现类,子接口的名称进行引用(而接口中的static方法不能被继承)))
  2. 调用接口中的静态方法
  3. 当初始化一个类时,将初始化这个类实现的所有的包含default方法的接口和超接口
  4. java.lang.reflect可能会导致接口初始化

初始化接口本身不会导致任何超接口的初始化(注意和第3条的区别)

对于这个问题我查阅了很多书籍和文章,都有讲得不太清楚的地方,所以不太确定结论是否正确,文章存在的疏漏读者也可以评论指正。

Java接口的初始化的更多相关文章

  1. [Java] 类和接口的初始化步骤 - 继承方面

    类和接口在初始化化时,处理继承层级的方法不一样. 类继承的初始化:通过引用 static 字段,触发某个类的初始化,则声明该字段的类,以及该类的父类被初始化. 接口继承的初始化:通过引用 static ...

  2. java接口

    一.定义 Java接口(Interface),是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为( ...

  3. Java系列笔记(1) - Java 类加载与初始化

    目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理解java其它机制将有重要作用. 每个类编译后产生一个 ...

  4. OpenCV4Android开发之旅(一)----OpenCV2.4简介及 app通过Java接口调用OpenCV的示例

    转自:  http://blog.csdn.net/yanzi1225627/article/details/16917961 开发环境:windows+ADT Bundle+CDT+OpenCV-2 ...

  5. Java中类的初始化

    类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.其中验证.准备.解析3个部分统称为连接.类加载的过程包括了加载.验证.准备.解 ...

  6. [Java] 类的初始化步骤

    前言 类的初始化过程,可在多线程环境下进行的,为了简化,本文介绍的单线程情况下的类初始化步骤. 此外,继承情况下的顺序不是本文焦点,本文重点在于一个类的内部字段的初始化顺序.想了解继承情况下的初始化情 ...

  7. Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...

  8. Java 类加载与初始化

    Java系列笔记(1) - Java 类加载与初始化 目录 类加载器 动态加载 链接 初始化 示例 类加载器 在了解Java的机制之前,需要先了解类在JVM(Java虚拟机)中是如何加载的,这对后面理 ...

  9. java类的初始化

    转载:http://blog.csdn.net/moreevan/article/details/6968718 我们知道一个类(class)要被使用必须经过装载,连接,初始化这样的过程.下面先对这三 ...

随机推荐

  1. 使用Java Stream,提取集合中的某一列/按条件过滤集合/求和/最大值/最小值/平均值

    不得不说,使用Java Stream操作集合实在是太好用了,不过最近在观察生产环境错误日志时,发现偶尔会出现以下2个异常: java.lang.NullPointerException java.ut ...

  2. SpringMVC-12-SSM回顾与总结

    12.SSM回顾与总结

  3. Linux实战(2):Linux传输文件

    此次使用的是scp命令,只是针对文件或者文件的传输,并没有什么高端的使用,主要是怕自己忘记了记一下. 传输文件,命令说明:scp+文件路径针确到文件名+账号+上传到另一台的路径并另存为文件名 scp ...

  4. Mysql-Innodb : 从一个字节到整个数据库表了解物理存储结构和逻辑存储结构

    首先要从Innodb怎么看待磁盘物理空间说起   一块原生的(Raw)物理磁盘,可以把他看成一个字节一个字节单元组成的物理存储介质   如果要在这块原生物理空间中插入一条记录,不能单单只插入数据,还需 ...

  5. Jaskson精讲第6篇-自定义JsonSerialize与Deserialize实现数据类型转换

    Jackson是Spring Boot(SpringBoot)默认的JSON数据处理框架,但是其并不依赖于任何的Spring 库.有的小伙伴以为Jackson只能在Spring框架内使用,其实不是的, ...

  6. Android动画系列之帧动画和补间动画

    原文首发于微信公众号:jzman-blog,欢迎关注交流! Android 提供三种动画:帧动画.补间动画和属性动画,本篇文章介绍帧动画以及补间动画的使用,属性动画的使用将在后面的文章中分享,那就来复 ...

  7. websocket+sockjs+stompjs详解及实例

    最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是考虑websocket在客户端的使用. 1.http ...

  8. RabbitMQ小记(三)

    1.RabbitMQ中mandatory和immediate以及备份交换机 (1)mandatory为true时,若交换机无法根据自身类型和路由键找到符合条件的对列,那么RabbitMQ会回调Basi ...

  9. c#RSA的SHA1加密与AES加密、解密

    前言:公司项目对接了一个对数据保密性要求较高的java公司.api接口逻辑是这样的:他们提供 SHA1私钥 与 AES的秘钥.我们需要将 传递查询参数 通过SHA1 私钥加密再转换成 十六进制 字符串 ...

  10. Python练习题 001:4个数字求不重复的3位数

    听说做练习是掌握一门编程语言的最佳途径,那就争取先做满100道题吧. ----------------------------------------------------------------- ...