java虚拟机-类型和对象的生命周期
- 格式:doc
- 大小:113.50 KB
- 文档页数:9
jvm的gc原理JVM的GC原理一、概述JVM(Java虚拟机)是Java程序运行的环境,其中最重要的组成部分之一就是垃圾回收(Garbage Collection,简称GC)机制。
GC的作用是自动管理程序中的内存,及时释放不再使用的对象,以避免内存泄漏和内存溢出的问题。
本文将对JVM的GC原理进行详细介绍。
二、垃圾回收算法1. 标记-清除算法标记-清除算法是最基本的垃圾回收算法之一。
它的过程分为两个阶段:标记阶段和清除阶段。
在标记阶段,GC会从根节点(一般是程序中的静态变量和栈中的引用)开始,递归地遍历对象图,标记出所有被引用的对象。
在清除阶段,GC会遍历整个堆,清除所有未被标记的对象。
2. 复制算法复制算法是针对标记-清除算法的改进。
它将堆分为两个区域,每次只使用其中一个区域。
当一个区域的对象被标记后,将其复制到另一个区域中,然后清除原来的区域。
这样可以解决碎片问题,但是需要额外的空间来存储复制的对象。
3. 标记-整理算法标记-整理算法是对标记-清除算法的改进。
它的过程与标记-清除算法类似,但是在清除阶段,标记-整理算法会将存活的对象向一端移动,然后清除边界外的所有对象。
这样可以解决碎片问题,并且不需要额外的空间。
4. 分代算法分代算法是针对对象的生命周期不同而提出的。
一般来说,对象的生命周期可以分为年轻代和老年代。
年轻代中的对象生命周期较短,老年代中的对象生命周期较长。
分代算法将堆分为年轻代和老年代两个区域,分别采用不同的垃圾回收算法。
年轻代一般使用复制算法,老年代一般使用标记-清除算法或标记-整理算法。
三、GC的执行过程1. 初始标记初始标记阶段是GC的第一步,它的目的是标记出所有的根对象,并且停止所有的应用线程。
这个过程是短暂的,因为只需要标记出与根对象直接关联的对象。
2. 并发标记并发标记阶段是GC的核心步骤,它的目的是通过并发执行来标记出所有的存活对象。
在这个阶段,GC会遍历整个堆,标记出与根对象直接或间接关联的存活对象。
Java高级程序设计认证试卷(答案见尾页)一、选择题1. Java语言的特性包括哪些?A. 封装B. 多态C. 抽象D. 动态代理2. 在Java中,以下哪个关键字用于定义常量?A. finalB. staticC. constD. var3. Java中的集合框架包含以下哪些接口?A. CollectionB. ListC. SetD. Map4. Java的异常处理机制包括以下哪些关键字?A. tryB. catchC. finallyD. throw5. 以下哪个是Java反射机制中用于获取类信息的方法?A. getDeclaredMethods()B. getGenericSuperclass()C. getAnnotations()D. getComponentType()6. Java的泛型支持以下哪种类型转换?A. 自动装箱/拆箱B. 自动类型转换C. 强制类型转换D. 隐式类型转换7. Java的注解处理器用于执行哪些任务?A. 代码重构B. 类文件生成C. 性能优化D. 错误检查8. 在Java中,以下哪个关键字用于实现接口?A. implementsB. extendsC. implementsD. extends9. Java的序列化机制用于以下哪个目的?A. 恢复内存中的对象状态B. 实现跨平台的数据交换C. 提高数据安全性D. 降低数据存储效率10. Java的线程同步机制使用的关键字是?A. synchronizedB. volatileC. lockD. await11. Java语言有哪些基本数据类型?A. byteB. shortC. intD. long12. 在Java中,以下哪个关键字用于定义方法?A. privateB. staticC. finalD. abstract13. Java中的集合框架包括哪些接口和实现类?A. ListB. SetC. QueueD. Map14. Java中,哪个关键字用于实现继承?A. extendsB. implementsC. interfaceD. override15. 在Java中,什么是垃圾回收机制(Garbage Collection)?A. 一种自动内存管理技术B. 一种手动内存管理技术C. 一种动态数组技术D. 一种静态数组技术16. Java中,哪个关键字用于导入其他包或类库?A. importB. includeC. requireD. uses17. 在Java中,什么是异常处理机制?请简述。
Java读书笔记第一篇:Java读书笔记读书笔记1、类和对象:类是用来定义一组对象共同具有的状态和行为的模版。
而对象是现实世界中个体或事物的抽象表示,并且封装了它们的属性和行为。
2、为了防止命名冲突,Java采用了管理类文件的机制,即类包机制。
(package)定义包名的语法格式:“package包名;”Java命名规则要求包的命名需要使用小写字母。
3、成员变量和成员方法:1成员变量是在类体中定义的变量即全局变量,○成员变量一般用于定义对象的状态。
成员变量是给对象使用的,每个对象被创建后都会有属于自己的属性,即成员变量。
通过修改这些属性,从而改变对象的某个状态。
2成员方法是对象行为的描述。
○定义成员方法的语法格式:“[修饰符] 返回值类型方法名([形参表]){······//方法体}”修饰符:可以是:publicprivateprotactedstaticfinall等;返回值类型:如果方法需要返回值,必须这里声明方法的返回值类型,可以是基本数据类型(int short double booleanvoid等),也可以是对象类型如:数组、字符串等。
形参表:(可选部分)说明方法被调用时应该向它传递的数据。
形参表可以有一个也可以有多个,当有多个形参时每个形参之间要用“,”隔开。
1创建对象:创建对象使用到new语句。
4、对象:○声明并创建对象的语法格式如下:“类名对象名=new 类构造方法()”构造方法:构造方法是类创建对象是必须执行的方法,用于构造一个新的对象并初始化对象属性。
2访问对象的属性:○语法格式:“对象名.属性”3执行对象的行为:○对象的行为就是对象的成员方法,通常说调用或执行对象的某个方法。
语法格式:“对象名.成员方法名();”4对象的销毁:Java提供了垃圾回收机制,对不再使用的对象会自动销毁,也可○以在程序中显式的为某个对象赋null值,使对象不再被使用。
java虚拟机的工作原理Java虚拟机(JVM)是Java程序运行的环境,它负责解释和执行Java字节码。
JVM的工作原理可以分为三个主要的部分:类加载、字节码执行和垃圾回收。
1.类加载:JVM通过类加载器将Java字节码加载到内存中。
类加载器根据类路径在文件系统或网络中查找并读取字节码文件,然后将其转化为JVM运行时数据结构,如类和方法的元数据。
加载完成后,JVM会在方法区中存储类的元数据,并在堆中分配内存来存储类的实例。
2.字节码执行:3.垃圾回收:JVM提供垃圾回收机制来自动释放不再使用的内存。
JVM会跟踪每个对象的引用,当一个对象没有引用时,即被视为垃圾。
垃圾回收器定期执行垃圾收集操作,释放垃圾对象占用的内存。
垃圾回收器有不同的实现策略,如标记-清除、引用计数、复制、标记-整理等。
除了以上三个主要的部分,JVM还包含其他组件,如堆内存、栈、方法区等。
堆内存用于存储对象实例,栈用于存储局部变量和方法调用参数,方法区用于存储类的元数据和静态数据。
JVM的工作过程如下:1. 通过类加载器加载Java字节码。
2.解释执行或JIT编译字节码。
3.根据需要进行垃圾回收和内存管理。
4.执行程序。
JVM的优点是跨平台性、自动内存管理和高性能。
通过JVM,Java程序可以在不同的硬件和操作系统上运行,无需修改源代码。
JVM的自动内存管理功能减轻了开发人员对内存管理的负担,避免了内存泄漏和越界访问等错误。
JVM的即时编译技术能够将热点代码优化为本地机器代码,提高程序的执行效率。
在实际的Java应用开发中,了解JVM的工作原理有助于编写高效的代码和解决性能问题。
开发人员可以通过调整JVM参数、选择合适的垃圾回收器和内存分配策略来优化程序的性能。
同时,了解JVM的工作原理还有助于理解虚拟机层面的问题和调优技巧,提升应用的可靠性和稳定性。
高级Java工程师面试题选择题各2分共44分1.下列说法正确的是A. Java语言不区分大小写B. Java程序以类为基本单位C. JVM为Java虚拟机JVM的英文缩写D. 运行Java程序需要先安装JDK答案:B,C,D2.下列说法中错误的是A. Java语言是编译执行的B. Java中使用了多进程技术C. Java的单行注视以//开头D. Java语言具有很高的安全性答案:A,B3.下面不属于Java语言特点的一项是A. 安全性B. 分布式C. 移植性D. 编译执行答案:D4.下列语句中,正确的项是A . int $ e,a,b=10;B. char c,d=’a’;C. float e=0.0d;D. double c=0.0f;答案ABD5.一个int 类型的常量和一个byte类型常量做减法,结果的类型是A. intB. byteC. charD. float答案A6.下列程序段的输出结果是public class Expressions{void printExpr(){int x=3,y=4,z=5;System.out.println(x+y+z);}}A. xyzB. x+y+zC. 12D. 9答案C7.下列关于for循环和while循环的说法中哪些是不正确的?A. for循环能实现的操作,while循环也都能实现B. for循环判断条件一般是非程序结果C. while循环判断条件一般是程序结果D. 两种循环结构中都必须有循环体,循环体不能为空答案ABC8.以下程序段执行后的K值为int x=10; y=34;k=(x<y)?y:x;A. 10B. 34C. 10D. 44答案B9.下列不属于Java语言流程控制结构是A.分支语句B.条转语句C.循环语句D.赋值语句E.答案D10.设定义语句:int a[ ]={43,44,45};则下面对此语句的叙述正确的是A.定义一个名为a的一维数组B.a数组有3个元素C.a数组的元素的下标为1~3D.数组中的每一个元素都是整型E.答案ABD11.运行以下代码public class Person{int array[]=new int[10];public static void main(String args[]){System.out.println(array [1]);}}正确的是A.编译时将产生错误B.编译时正确,运行时将产生错误C.输出零D.输出空答案A12.执行完下面语句int[ ]x = new int[20]; 后,说法正确的是A.x[19]为0B.x[19]未定义C.x[20]为0D.x[0]为空答案A13.设tmp是一个数组类成员,以下声明并初始化一个4个元素的数组选项A.int tmp[]={1,2,3,4};B.int tmp[]=new int[5];C.int tmp[]=new int(5);D.int tmp[];答案A14.设定义:String s=”cake”,下面不合法的有A.s=s. toUpperCase();B.char c=s[1];C.int len=s.length;D.s=s.trim();答案BC15.设String s1=”Hello”;String s2=”World”;以下方法用来得到字符串“Hello World”有A.s2+s1;B.s1.concat(s2);C.s1.append(s2);D.s1.concate(s2);答案B16.下面哪一个是Java最基本的元素A. 接口B. 方法C. 包D. 对象答案:D17.如果Cake.java、Ball.java这两个类总共包含有8个方法,则编译后会产生多少个字节码文件A. 12B. 10C. 2D. 1答案:C18.下面关于抽象类的理解,错误的是A. 构造方法可以声明为抽象类型B. 抽象方法必须被子类的方法覆盖C. 不允许实现抽象方法D. 方法声明中,static 和abstract不能同时存在答案:A19.编译Java程序时编译器提示找不到要编译的代码,这种错误通常可能是A. 文件名拼写错误B. 没有导入相应的包C. 文件名不是.javaD. 源文件不在Java搜索路径中答案:A,C,D20.捕获异常应该使用下列哪个子句A. throwB. catchC. finallyD. throws答案:B21.下列哪一项不属于finally语句的工作A. 关闭数据库B. 释放资源C. 关闭文件D.分配资源答案:D22.下面哪些需要异常处理机制A. 编译出错B. 方法、类中抛出的异常C. 使系统从故障中恢复D. 程序因不可避免的原因产生错误答案:B,C,D简述题每题3分共18分(1)用final声明属性、方法和类时,被声明的属性、方法和类表现出哪些特性?下面的实例正确吗?如果不正确,请说明原因?实例:final Test t = new Test();t.setName(“Jack”);答:final 用于声明属性,方法和类,分别表示属性不可变,方法不可覆盖,类不可继承。
深入理解java虚拟机(一)虚拟机内存划分Java虚拟机在执行Java程序时,会把它管理的内存划分为若干个不同的数据区。
这些区域有不同的特性,起不同的作用。
它们有各自的创建时间,销毁时间。
有的区域随着进程的启动而创建,随着进程结束而销毁,有的则始终贯穿虚拟机整个生命周期。
Java虚拟机运行时内存区域主要分为七部分,分别是:程序计数器,Java虚拟机栈,本地方法栈,方法区,Java堆,运行时常量池,直接内存。
如上图所示(图片来源于网络):蓝色区域包裹的部分为运行时几个数据区域:白色的部分为线程私有的,既随着线程的启动而创建。
每个线程都拥有各自的一份内存区域。
它们是:JAVA栈(JAVA STACK),本地方法栈(NATIVE METHOD STACK),和程序计数器(PROGRAM COUNTER REGISTER)。
黄色部分是线程共享的,所有的线程共享该区域的内容。
他们是:方法区(METHOD AREA),堆(HEAP)。
我们分别来介绍这些区域。
(1)程序计数器(program counter register)学过计算机组成原理的都知道计算机处理器中的程序计数器。
当处理器执行一条指令时,首先需要根据PC中存放的指令地址,将指令由内存取到指令寄存器中,此过程称为“取指令”。
与此同时,PC中的地址或自动加1或由转移指针给出下一条指令的地址。
此后经过分析指令,执行指令。
完成第一条指令的执行,而后根据PC取出第二条指令的地址,如此循环,执行每一条指令。
处理器的程序计数器是指寄存器,而java程序计数器是指一小块内存空间。
java代码编译字节码之后,虚拟机会一行一行的解释字节码,并翻印成本地代码。
这个程序计数器盛放的就是当前线程所执行字节码的行号的指示器。
在虚拟机概念模型中,字节码解释器工作室就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理等都依赖于它。
Java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式实现的,因此为了线程切换后还能恢复执行位置,每条线程都需要一个独立的程序计数器。
java 对象的创建过程Java是一种面向对象的编程语言,对象是Java程序的基本构建单元。
在Java中,对象的创建过程包括类的定义、实例化、构造方法的调用和内存分配等步骤。
本文将详细介绍Java对象的创建过程。
一、类的定义在Java中,对象的创建首先需要定义类。
类是对象的模板,定义了对象的属性和行为。
类可以包含成员变量、方法和构造方法等成员。
成员变量用于描述对象的属性,方法用于描述对象的行为。
构造方法是一种特殊的方法,用于初始化对象的成员变量。
类的定义通常包括类名、成员变量、方法和构造方法等部分。
二、实例化对象的实例化是指根据类的定义创建对象的过程。
在Java中,使用关键字"new"来实例化对象。
通过"new"关键字可以调用类的构造方法创建对象,并返回对象的引用。
实例化一个对象需要指定类名和构造方法的参数。
三、构造方法的调用构造方法是一种特殊的方法,用于初始化对象的成员变量。
在Java 中,每个类都至少有一个构造方法。
当实例化一个对象时,会调用该类的构造方法。
构造方法的名称与类名相同,没有返回值。
构造方法可以有参数,用于传递初始化对象所需的数据。
通过构造方法可以给对象的成员变量赋初始值。
四、内存分配在Java中,对象的创建需要在内存中分配空间。
Java的内存分配是由Java虚拟机(JVM)自动完成的。
当调用"new"关键字创建对象时,JVM会在堆内存中分配一块空间,用于存储对象的成员变量和方法。
同时,JVM会自动管理对象的生命周期,包括内存的分配和释放。
五、对象的初始化对象的初始化是指在对象创建完成后,对对象的成员变量进行赋值的过程。
在Java中,对象的成员变量可以在定义时赋初值,也可以在构造方法中赋值。
对象的初始化可以根据实际需求进行,可以通过构造方法传入参数,也可以通过调用对象的成员方法进行。
六、对象的使用对象创建完成后,可以通过对象的引用来访问对象的成员变量和方法。
javaee面试题目及答案一、介绍在JavaEE开发领域,面试是获得理想职位的重要环节之一。
本文将为您提供一些常见的JavaEE面试题目及其答案,帮助您在面试中更好地展示自己的技能和知识。
二、Java基础1. 什么是Java语言?Java语言是一种面向对象的高级程序设计语言,拥有跨平台特性,由Sun Microsystems于1995年开发。
2. Java和C++有什么区别?Java是一种解释型语言,不依赖于特定操作系统,而C++是一种编译型语言。
此外,Java具有垃圾回收机制和自动内存管理,而C++需要手动处理内存。
3. 描述Java的特性。
Java具有以下特性:- 简单性:Java语法相对简单,易于学习和使用。
- 面向对象:Java支持面向对象的编程范式,并提供封装、继承和多态等特性。
- 平台无关性:Java程序可以在任何支持Java虚拟机(JVM)的平台上运行。
- 安全性:Java有安全管理机制,可以防止恶意代码的执行。
- 可移植性:Java程序可以在不同操作系统和硬件平台上无需修改而运行。
- 多线程:Java支持多线程编程,可以实现多个任务的并发执行。
- 高性能:Java通过即时编译器(JIT)实现高效的执行速度。
4. 什么是Java虚拟机(JVM)?Java虚拟机是Java程序的运行环境,负责解释和执行Java字节码。
不同的操作系统需要使用相应的JVM来运行Java程序。
5. 解释Java的垃圾回收机制。
Java的垃圾回收机制是自动内存管理的重要组成部分。
垃圾回收器会自动识别和回收不再使用的内存,开发者无需手动释放内存。
这样可以有效避免内存泄漏和内存溢出的问题。
6. 什么是Java的异常处理机制?Java的异常处理机制用于处理程序执行过程中可能出现的错误或异常情况。
通过在代码中捕获异常并进行处理,可以提高程序的健壮性和可靠性。
三、JavaEE框架1. 什么是JavaEE框架?JavaEE框架是用于简化企业级应用程序开发的一套工具和组件集合。
gc 基本数据类型和对象在Java中,基本数据类型和对象是程序员必须掌握的两个重要概念。
基本数据类型指的是Java中八种基本数据类型,包括byte、short、int、long、float、double、char和boolean。
这些基本数据类型在Java中的存储方式是按值传递,即在方法调用时,传递的是值的副本,而不是原值本身。
基本数据类型的值存储在Java虚拟机的栈中,它们的生命周期随着方法的结束而结束。
对象则是指在Java中由类生成的实例,它们有自己的状态和行为,可以通过调用对象的方法来改变它们的状态和行为。
对象在Java 中的存储方式是引用传递,即在方法调用时,传递的是对象的引用,而不是对象本身。
对象的引用存储在Java虚拟机的堆中,它们的生命周期比基本数据类型更长,需要通过垃圾回收器来回收。
在Java中,垃圾回收器(GC)是负责回收堆中无用对象的机制。
垃圾回收器通过检查对象是否被引用来判断是否需要回收该对象。
如果对象的引用计数为0,则该对象将被回收。
垃圾回收器的实现是Java虚拟机的一部分,它可以通过不同的算法来实现垃圾回收,如标记-清除算法、复制算法、标记-整理算法等。
需要注意的是,在Java中,基本数据类型和对象的存储方式不同,因此它们的性能也不同。
在处理数据量较大的情况下,使用基本数据类型可以提高程序的执行效率。
而在处理需要更多状态和行为的情况下,使用对象则更为合适。
在使用对象时,需要注意对象的生命周期,避免出现内存泄漏和内存溢出等问题。
综上所述,基本数据类型和对象是Java编程中两个重要的概念,需要程序员深入理解它们的存储方式、性能特点和使用规范,以提高程序的效率和可靠性。
这一章以一个Java类型(类或接口)的生命周期为例来讨论开始阶段的装载、连接和初始化,以及占Java类型生命周期绝大部分时间的对象实例化、垃圾收集和对象终结,然后是java类型生命周期的结束,也就是从虚拟机中卸载。
7.1、类型装载、连接与初始化Java虚拟机通过装载、连接和初始化一个Java类型,使该类型可以被正在运行的java程序所使用。
其中,类装载就是把二进制形式的Java类型读入Java虚拟机中;而连接就把这种已经读入虚拟机的二进制形式的类型数据合并到虚拟机的运行时状态中去。
连接阶段分为三个子步骤——验证、准备和解析。
“验证”步骤确保了Java类型数据格式正确并且适于Java虚拟机使用。
“准备”步骤则负责为该类型分配它所需的内存,比如为它的类变量分配内存。
“解析”步骤则负责把常量池中的符号引用转换为直接引用。
虚拟机的实现可以推迟解析这一步,它可以在当运行中的程序真正使用某个符号引用时再去解析它。
之后,进行初始化,在初始化期间,都将给类变量赋以适当的初始值。
在类和接口被装载和连接的时机上,java虚拟机规范没有严格的规定,但是它严格的定义了初始化的时机,所有的Java虚拟机实现必须在每个类或接口首次主动使用时初始化。
下面六种情况符合主动使用的要求:1)、当创建某个类的实例时(通过new指令或通过不明确的创建、反射、克隆、反序列化)2)、当调用某个类的静态方法时3)、当使用某个类或接口的静态字段,或者对该字段赋值时。
(final修饰的静态字段除外,它被初始化为一个编译时的常量表达式)4)、当调用Java API中的某些反射方法时,比如类Class中的方法或者ng.reflect 包中的类的方法5)、当初始化某个类的子类时(某个类初始化时,要求它的超类已经被初始化了)6)、当虚拟机启动时某个被标明为启动类(即含有main()方法的那个类)注:任何一个类的初始化都要求它的所有祖先类预先初始化,而一个接口的初始化,并不要求它的祖先接口预先被初始化。
也就是说只有某个接口所声明的非常量字段被使用时,该接口才会被初始化,而不会因为实现这个接口的子接口或类要初始化而被初始化。
但是当实现了父接口的子类(或扩展了父接口的子接口)被装载时,父接口也必须被装载。
7.1.1装载装载阶段有三个基本动作组成,要装载一个类型,Java虚拟机必须:1)、通过该类型的完全限定名,产生一个代表该类型的二进制数据流。
2)、解析这个二进制数据流为方法区内的内部数据结构。
3)、创建一个表示该类型的ng.Class类型的实例(装载步骤最终的产品就是这个Class类的实例对象,它成为程序与内部数据结构之间的接口,要访问关于该类型的信息,程序就要调用该类型对应的Class实例对象的方法)。
7.1.2验证装载后就要进行连接了,连接过程的第一步是验证——确认类型符合Java语言的语义,并且它不会危及虚拟要的完整性。
其实有一些特定的检查并不发生在验证这一步,如:1)、在装载过程中,虚拟机大多会检查二进制数据以确保数据全部都是预期的格式(符合java class文件格式);2)、在装载时,还要确保除了Object类之外的每一个类都有一个超类,因为装载一个类的时候必须确保该类的所有超类都已经被装载了。
3)、还有一种检查往往发生在验证阶段之后,那就是符号引用的验证,当虚拟机搜寻一个被符号引用的元素(类型、字段和方法)时,它必须首先确认该元素存在,如果虚拟机发现元素存在,它必须进一步检查引用类型有访问该元素的权限。
那么验证阶段做哪些检查呢,如下:1、确保各个类之间二进制兼容的检查1)、检查final的类不能拥有子类。
2)、检查final的方法不能被覆盖3)、确保在类型和超类型之间没有不兼容的方法声明(例如两个方法拥有同样的名字,参数在数量和顺序类型上都相同,但是返回类型不同)2、检查所有的常量池入口相互之间一致3、检查常量池中的所有的特殊字符串(类名、字段名、和方法名、字段描述符和方法描述符是否符合格式)4、检查字符字节码的完整性(这是最复杂的任务,所有java虚拟机都必须设法为它们执行的每个方法检验字节码的完整性)7.1.3准备在准备阶段,Java虚拟机为类变量分配内存,设置默认初始值。
但到达初始化阶段之前,类变量都没有被初始化为真正的初始值,在准备阶段是不会执行java代码的。
Char类型默认为’\u0000’,byte默认为(byte)0,boolean默认为0,float默认为0.0f,double 默认为0.0d,long默认为0L。
7.1.4 解析解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用的过程。
7.1.5 初始化在java代码中,一个正确的初始值是通过类变量初始化语句或者静态初始化语句给出的。
所有的类变量初始化语句和类型的静态初始化器都被java编译器收集在一起,放到一个特殊的方法中,称为类初始化方法。
在类和接口的Java class文件中,这个方法被称为”<clinit>”。
通常的Java程序方法是无法调用这个<clinit>方法的,只能被java虚拟机调用。
初始化一个类包含两个步骤:1)、如果类存在直接超类的话,且直接超类还没有被初始化,就先初始化直接超类。
2)、如果类存在一个类初始化方法(<clinit>)就执行此方法。
注:初始化一个接口只需一步:如果接口存在一个接口初始化方法的话,就执行此方法。
初始化的顺序按照类变量初始化语句和静态初始化语句出现的顺序初始化。
并不是所有的类都需要在它的class文件中有一个<clinit>()方法。
如果类没有声明任何类变量,也没有静态初始化语句,那么它就不会有<clinit>()方法。
如果类声明了类变量,但是没有明确使用类变量初始化语句或者静态初始化语句初始化它们,那么类也不会有<clinit>()方法。
所有在接口中声明的隐式公开(publict)、静态(static)、最终(final)字段必须在字段初始化语句中初始化,如果接口包含任何不能在编译时被解析成为一个常量的字段初始化语句,接口就拥有一个<clinit>()方法。
例如:[java]view plaincopyprint?1.interface Example{2.3. intketchup = 5;4.5. int mustard= (int) (Math.random()*5.0);6.7.}8.9.10.11. ketchup将会被初始化为一个编译时常量,而mustard字段被<clinit>()方法初始化。
12.13. 主动使用与被动使用14.15. 在第六章中曾提到主动使用类类型的6种情况,他们会引发初始化。
当使用一个非常量的静态字段时,只有这个字段是被当前类或接口声明的情况下才是主动使用,如果是子类使用父类中声明的字段,子接口和实现了该接口的类使用此接口中的字段都被认为是被动使用,不会引发初始发,例如:16.17. public class NewParent {18.19. static int hoursOfsleep = (int)(Math.random()*3.0);20.21. static{22.23. System.out.println("NewParentwas initialized");24.25. }26.27. }28.29. public class NewbornBaby extends NewParent {30.31.32.33. static int housOfCrying = 6+(int)(Math.random()*2.0);34.35. static{36.37. System.out.println("NewbornBabywas initialized.");38.39. }40.41. }42.43. public class Example {44.45. static{46.47. System.out.println("Example wasinitialized.");48.49. }50.51. public static void main(String[] args) {52.53. int hours = NewbornBaby.hoursOfsleep;54.55. System.out.println(hours);56.57. }58.59. }实例化一个类有四种途径:明确地使用new操作符;调用Class或者ng.reflect.Constructor对象的newInstance()方法;调用任何现有对象的clone()方法;或者通过java.io.ObjectInputStream类的getObject()方法反序列化。
除了明确地实例化对象之外,还有几种情况下会隐含地实例化,例如:1)在任何java程序中第一个隐含实例化对象可能就是保存命令行参数的String对象。
2)对于java虚拟机装载的每一个类型,它会暗中实例化一个Class对象来代表这个类型。
3)当Java虚拟机装载了在常量池中包含CONSTANT_String_info入口的类的时候,它会创建新的String对象的实例来表示这些常量字符串。
4)另一种隐含创建对象的途径是通过执行包含字符串连接操作符的表达式产生对象。
当Java虚拟机创建一个类的实例时,首先都需要在堆中为保存对象的实例变量分配内存(所有在对象的类中和它的超类中声明的变量都要分配内存)。
准备好内存后,它立即把实例变量初始化为默认的初始值。
一旦虚拟机完成了新对象的分配内存和为实例变量赋默认初始值后,它随后就会为实例变量赋正确的初始值,这一步会有三种情况:1)如果对象是通过clone()调用来创建的,虚拟机把原来被克隆的实例变量中的值拷贝到新对象中。
2)如果对象是调用一个ObjectInputStream的readObject()调用反序列化的,虚拟机通过从输入流中读入的值来初始化那些非暂时性的实例变量。
3)虚拟机调用对象的实例初始化方法。
Java编译器为它编译的每一个类都至少生成一个实例初始化方法。
在Java的class文件中,这个实例初始化方法称为”<init>”。
一个<init>()方法中可能包含三种代码:调用另一个<init>()方法;实现对任何实例变量的初始化;构造方法体的代码。
一个类的构造方法有如下几种情况:1、如果构造方法通过明确地调用同一个类中的另一个构造方法(一个this()调用)开始,它对应的<init>()方法由两部分组成:1)、一个同类的<init>()方法的调用2)、实现了对应构造方法的方法体的字节码2、如果构造方法不是通过一个this()调用开始的,而且这个对象不是Object,<init>()方法则由三部分组成:1)、一个超类的<init>()方法的调用2)、任意实例变量初始化方法的字节码3)、实现了对应构造方法的方法体的字节码3、如果构造方法没有使用一个this()调用开始,而且这个对象是Object,则上面列表中的第一个元素就不存在,因为Object没有超类。