对类的使用方式分为:主动使用、被动使用

所有的java虚拟机实现必须在每个类或接口被java程序“首次主动使用”时才初始化他们

ps:被动使用不会初始化类,但是有可能会加载类(JVM规范里没有说明)

并且,如果在加载的过程中,遇到了.class文件的缺失或者存在错误,类加载器只会在首次主动使用它们时才会报错,如果一直没有主动使用,则不会报错

主动使用:

创建类的实例、访问某个类或者接口的非final类型的静态变量/对该静态变量赋值、调用类的静态方法、反射、初始化一个类的子类、jvm启动时被标明为启动类的类(如Java Test、main方法所在的类)、jdk1.7开始提供动态语言的支持相关(很少使用)

ps:

初始化一个类的子类这条规则,不适用于接口,即:初始化一个类的子类,会先初始化它的父类,但是不一定会初始化它的接口。只有当首次使用该接口的静态变量时,才会初始化。

被动使用:

除了主动使用的其他使用方式

(1)通过子类引用父类的静态字段,为子类的被动使用,不会导致子类初始化

 1 class Dfather{
2 static int count = 1;
3 static{
4 System.out.println("Initialize class Dfather");
5 }
6 }
7
8 class Dson extends Dfather{
9 static{
10 System.out.println("Initialize class Dson");
11 }
12 }
13
14 public class Test4 {
15 public static void main(String[] args) {
16 int x = Dson.count;
17 }
18 }
 

上面这个例子中,虽然是以Dson.count 形式调用的,但是因为count是Dfather的静态成员变量,所以只初始化Dfather类,而不初始化Dson类

(2)通过数组定义类引用类,为类的被动使用,不会触发此类的初始化

原因:其实数组已经不是E类型了,E的数组jvm在运行期,会动态生成一个新的类型,新类型为:

如果是一维数组,则为:[L+元素的类全名;二维数组,则为[[L+元素的类全名

如果是基础类型(int/float等),则为[I(int类型)、[F(float类型)等

 1 class E{
2 static{
3 System.out.println("Initialize class E");
4 }
5 }
6
7 public class Test5 {
8 public static void main(String[] args) {
9 E[] e = new E[10];
10 }
11 }
 

(3)常量在编译阶段会存入调用方法所在的类的常量池中(这个例子存在F类的常量池中),本质上没有直接引用到定义常量的类,因此不会触发定义常量的类的初始化

在本例子中,编译好了Test6后,类Test6和类F就完全没有关系了,甚至,你可以把类F的class文件删掉,也不影响程序的正常执行

 1 class F{
2 static final int count = 1;
3 static{
4 System.out.println("Initialize class F");
5 }
6 }
7
8 public class Test6 {
9 public static void main(String[] args) {
10 int x = F.count;
11 }
12 }
 

如上例中,F类中定义的count是final对象,其在编译阶段就会存入调用类的常量池中

但是,如果把代码改成

 1 class F{
2 static final String s = UUID.randomUUID().toString();
3 static{
4 System.out.println("Initialize class F");
5 }
6 }
7
8 public class Test6 {
9 public static void main(String[] args) {
10 String x = F.s;
11 }
12 }
 

则语句 "Initialize class F" 会打印出来,因为UUID.randomUUID().toString()这个方法,是运行期确认的,所以,这不是被动使用

java类的主动使用/被动使用的更多相关文章

  1. Java Web:主动和被动方式检测安全的框架

    对于某些敏感的系统例如支付.交易需要为其加固,有必要将可能的攻击情况考虑进来加以防范,于是有了这么一个简易的安全框架.在前辈的代码上( 详见 :http://blog.csdn.net/zhongwe ...

  2. 深入剖析Classloader(一)--类的主动使用与被动使用

    原文地址:http://yhjhappy234.blog.163.com/blog/static/3163283220115573911607 我们知道java运行的是这样的,首先java编译器将我们 ...

  3. 所有的Java虚拟机必须实现在每个类或接口被Java程序 “ 首次主动使用 ” 时才初始化他们

    原文:https://www.cnblogs.com/fanjie/p/6916784.html Java程序对类的使用方式可分为两种– 主动使用– 被动使用 被动使用以后再讲,这里说说什么是主动使用 ...

  4. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  5. 解析Java类和对象的初始化过程

    类的初始化和对象初始化是 JVM 管理的类型生命周期中非常重要的两个环节,Google 了一遍网络,有关类装载机制的文章倒是不少,然而类初始化和对象初始化的文章并不多,特别是从字节码和 JVM 层次来 ...

  6. java类生命周期详细解析

    (一)详解java类的生命周期 引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前 ...

  7. Java类的生命周期详解

    引言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大多只是告 ...

  8. 【转】Java 类的生命周期详解

    一. 引 言 最近有位细心的朋友在阅读笔者的文章时,对java类的生命周期问题有一些疑惑,笔者打开百度搜了一下相关的问题,看到网上的资料很少有把这个问题讲明白的,主要是因为目前国内java方面的教材大 ...

  9. JVM中java类的加载时机(转载:http://blog.csdn.net/chenleixing/article/details/47099725)

    Java虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的加载机制.类从被加载到虚拟机内存中开始,到卸载出内 ...

随机推荐

  1. 【开发工具】 使用阿里的 Teambition 跟踪BUG修复及需求管理

    刚入公司几个月,公司新项目一直没有用协作工具进行BUG管理,公司也没有专业的测试工程师. 第一阶段开发到了尾声,工作效率实在太低,随决定使用一个比较现代一点的管理工具. 在众多在线项目协作软件中,我选 ...

  2. python-列表list和元组tuple

    list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时添加和删除其中的元素. 比如,列出班里所有同学的名字,就可以用一个list表示: >>> ...

  3. jQuery笔记(一)

    day01 - jQuery 学习目标: 能够说出什么是 jQuery 能够说出 jQuery 的优点 能够简单使用 jQuery 能够说出 DOM 对象和 jQuery 对象的区别 能够写出常用的 ...

  4. this作为构造函数时注意点

    在 JS 中,为了实现类,我们需要定义一些构造函数,在调用一个构造函数的时候加上 new 这个关键字: function Person(name) { this.name = name; consol ...

  5. Python排序函数用法

    Python排序函数完美体现了Python语言的简洁性,对于List对象,我们可以直接调用sort()函数(这里称为"方法"更合适)来进行排序,而对于其他可迭代对象(如set,di ...

  6. 高速缓冲存储器Cache

    目录 概述 问题的提出 局部性原理 命中与未命中 Cache的命中率 Cache-主存系统的效率 例题 工作原理 地址映射方式(本节最重要) 直接映射 全相联映射 组相联映射 例子 替换策略 例题 写 ...

  7. Day1 input&print

    1.print函数 格式: 打印字符串:print('xxx','yyy') 可以接受多个字符串,多个字符串之间使用逗号分隔. 间隔字符串的逗号会被打印成空格输出. 打印整数或计算结果:print(' ...

  8. 目前市面上比较流行的devops运维平台汇总

    1,spug 1,Spug简介 Spug是面向中小型企业设计的无 Agent的自动化运维平台,整合了主机管理.主机批量执行.主机在线终端.应用发布.任务计划.配置中心.监控.报警等一系列功能.演示地址 ...

  9. Unity射击实例讲解—主角创建

    前言: 经过三分钟的思考决定换个标题,这两天其实游戏制作进度推了大半了,加入了许多自我创作的素材,不过想一想用来讲解的实例不该这么花哨,决定还是参照我的一些教材做一些简单的示例不然要说的东西太多,本人 ...

  10. 网络编程-python实现-socket(1.1.1)

    @ 目录 1.不同电脑进程之间如何通信 2.什么是socket 3.创建socket 1.不同电脑进程之间如何通信 利用ip地址 协议 端口 标识网络的进程,网络中的进程通信就可以利用这个标志与其他进 ...