背景

接口与类真正有所区别的是前面讲述的四种“有且仅有”需要开始初始化场景中的第三种:当一个类在初始化时,要求其父类全部都已经初始化过了,但是一个接口在初始化时,并不要求其父接口全部都完成了初始化,只有在真正使用到父接口的时候(如引用接口中定义的常量)才会初始化。 ——《深入理解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. springboot之启动端口指定

    https://www.cnblogs.com/yaomajor/p/8616929.html

  2. 吾日三省吾身 java核心代码 高并发集群 spring源码&思想

    阿里面试题    未解决https://my.oschina.net/wuweixiang/blog/1863322 java基础  有答案  https://www.cnblogs.com/xdp- ...

  3. Netty中的一些注意事项--底层基础

    转载自http://www.mamicode.com/info-detail-1215305.html 最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty.在使用过程中一边优化 ...

  4. Qt 展示pdf内容(新窗口或嵌入,pdfjs,linux)

    前言:初学Qt,在网上查找了诸多资料,有什么poppler.mupdf啊巴拉巴拉的,结果一个比一个费劲,最后还是采用pdfjs较为方便高效,为方便相关问题搜索,写了一下内容. 需求描述:Qt应用中不支 ...

  5. 基于docker部署jenkins

    1. 拉镜像 和其他的部署的镜像的方式一样,通常是直接使用docker search jenkins 然后直接docker pull jenkins 此时,在安装插件的时候发现插件都安装失败,提示je ...

  6. Spring Boot 项目打成 war 包部署

    Spring Boot 一个非常方便的功能就是支持内置的 Servlet 容器,一般我们部署 Spring Boot 应用时都是打成一个可执行的 Jar 包进行部署.其实 Spring Boot 也是 ...

  7. Jboss未授权访问漏洞复现

    一.前言 漏洞原因:在低版本中,默认可以访问Jboss web控制台(http://127.0.0.1:8080/jmx-console),无需用户名和密码. 二.环境配置 使用docker搭建环境 ...

  8. eureka集群的搭建

    本次将会创建三个注册中心和一个客户端进行集群,架构图如下: 修改本机hosts文件,创建三个域名: 代码结构如图: 由于三个注册中心结构都是一样的,区别在于配置文件: #注册中心(eureka-ser ...

  9. 数论(8):min_25 筛(扩展埃氏筛)

    min_25 筛介绍 我们考虑这样一个问题. \[ans=\sum_{i = 1}^nf(i)\\ \] 其中 \(1 \le n \le 10^{10}\) 其中 \(f(i)\) 是一个奇怪的函数 ...

  10. Win7 64X 安装VisualSVNServer 2.6.0过程中出现Custom action InstallWMISchemaExcute failed: Cannot query proxy blanket: No such interface supported (0x80004002)

    Win7 64X 安装VisualSVNServer 2.6.0过程中出现错误:Custom action InstallWMISchemaExcute failed: Cannot query pr ...