java 初始化方法_Java初始化理解与总结

Java的初始化可以分为两个部分:

(a)类的初始化

(b)对象的创建

(a)类的初始化

**一、概念介绍: ** 一个类(class)要被使用必须经过装载,连接,初始化这样的过程。

在装载阶段,类装载器会把编译形成的class文件载入内存,创建类相关的Class对象,这个Class对象封装了我们要使用的类的类型信息。

连接阶段又可以分为三个子步骤:验证、准备和解析。

验证就是要确保java类型数据格式 的正确性,并适于JVM使用。

准备阶段,JVM为静态变量分配内存空间,并设置默认值,注意,这里是设置默认值,比如说int型的变量会被赋予默认值0 。在这个阶段,JVM可能还会为一些数据结构分配内存,目的是提高运行程序的性能,比如说方法表。

解析过程就是在类型的常量池中寻找类、接口、字段和方法的符号引用,把这些符号引用替换成直接引用。这个阶段可以被推迟到初始化之后,当程序运行的过程中真正使用某个符号引用的时候 再去解析它。

类的初始化:

初始化类,是指初始化static静态变量和执行static静态代码块。

初始化接口,是指初始化定义在该接口中的filed。

二、类的初始化条件:

类会在首次被“主动使用”时执行初始化,以下情况第一次发生之前类会被初始化:

创建类的实例;

调用类的静态方法;

调用类的静态变量,并且该变量不是一个常变量;

为类的静态字段赋值;

在顶层类中执行assert语句;(?)

调用类Class及包java.lang.reflect中的某些反射方法;

JLS严格的说明:在任何其他的情况下,都不会对类或接口进行初始化。

三、类的初始化规则:

类初始化时,该类的父类将首先被初始化,此过程一直递归到 java.lang.Object为止。但是父类实现的接口并不会被初始化。

class Parent implements J{

{ System.out.println("父类初始化块"); }

static{

System.out.println("父类静态初始化块");

}

}

class Child extends Parent implements I{

{ System.out.println("子类初始化块"); }

static{

System.out.println("子类静态初始化块");

}

}

interface I {

int i = Test.out("interface : i", 1);

}

interface J {

int j = Test.out("interface : j", 2);

}

public class Test {

static int out(String s, int i) {

System.out.println(s + "=" + i);

return i;

}

public static void main(String [] args){

new Child();

}

}

接口只有被用到时才会被初始化

输出:

父类静态初始化块

子类静态初始化块

父类初始化块

子类初始化块

接口初始化时,只会初始化该接口本身,并不会初始化它的父接口。

interface I {

int i = Test.out("interface : i", 1);

int ii = Test.out("interface : ii", 11);

}

interface J extends I{

int j = Test.out("interface : j", 2);

int jj = Test.out("interface : jj", 22);

}

public class Test {

static int out(String s, int i) {

System.out.println(s + "=" + i);

return i;

}

public static void main(String [] args){

System.out.println(J.j);

}

}

输出:

interface : j=2

interface : jj=22

2

如果类的初始化是由于访问静态域而触发,那么只有真正定义该静态域的类才被初始化,而不会触发超类的初始化或者子类的初始化即使静态域被子类或子接口或者它的实现类所引用。

示例1:(如上所述)

class Parent{

static int p = 10;

static{

System.out.println("父类静态初始化块");

}

}

class Child extends Parent{

static int c = 20;

static{

System.out.println("子类静态初始化块");

}

}

public class Test {

public static void main(String [] args){

System.out.println(Child.p); //静态域p被子类引用

}

}

父类静态初始化块

10

示例2:(满足类的初始化条件,父类也会被初始化,与示例1不同)

public class Test {

public static void main(String [] args){

System.out.println(Child.c);

}

}

父类静态初始化块

子类静态初始化块

20

如果一个静态变量是编译时常量,则对它的引用不会引起定义它的类的初始化。

示例1:

class Parent{

static{

System.out.println("父类静态初始化块");

}

}

class Child extends Parent{

static final int x = 2005;

static{

System.out.println("子类静态初始化块");

}

}

public class Test {

public static void main(String [] args){

System.out.println(Child.x);

}

}

输出:

2005

示例2:(I.i是一个编译时常量,因此它不会引起I被初始化。)

interface I {

int i = 1;

int ii = Test.out("ii", 2);

}

public class Test {

static int out(String s, int i) {

System.out.println(s + "=" + i);

return i;

}

public static void main(String [] args){

System.out.println(I.i);

}

}

1

初始化类是指初始化static静态变量和执行static静态代码块,所以只会进行一次。

初始化接口也只会进行一次。

示例1:

class Child extends Parent{

static int c = 20;

static{

System.out.println("子类静态初始化块");

}

}

public class Test {

public static void main(String [] args){

System.out.println(Child.c);

System.out.println(Child.c);

}

}

父类静态初始化块

子类静态初始化块

20

20

示例2:

interface J{

int j = Test.out("j", 3);

int jj = Test.out("jj", 4);

}

public class Test {

static int out(String s, int i) {

System.out.println(s + "=" + i);

return i;

}

public static void main(String [] args){

System.out.println(J.j);

System.out.println(J.j);

}

}

j=3

jj=4

3

3

(b)对象创建过程中的Java初始化

一. 对象的创建过程总结

假设有个名为Dog的类:

当首次创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位Dog.class文件。

然后载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化只在class对象首次加载的时候进行一次。

当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。

这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成了默认值(对数字来说就是0,对布尔型与字符型也相同),而引用则被设置成了null。

执行所有出现于字段定义处的初始化动作。

执行构造器。

---《Thinking in java》

二. 对象创建过程中初始化顺序

父静态成员>子静态成员>父普通成员初始化>父构造>子普通成员初始化>子构造.

( 静态初始化块以静态变量对待)

示例1:

public class Test {

public static void main(String [] args){

new Child();

}

}

class Parent{

{

System.out.println("父类普通成员初始化块");

}

static{

System.out.println("父类静态成员及初始化块");

}

public Parent(){

System.out.println("父类构造函数");

}

}

class Child extends Parent{

{

System.out.println("子类普通成员初始化块");

}

static{

System.out.println("子类静态成员及初始化块");

}

public Child(){

super();

System.out.println("子类构造函数");

}

}

父类静态成员及初始化块

子类静态成员及初始化块

父类普通成员初始化块

父类构造函数

子类普通成员初始化块

子类构造函数

示例2:(证明 父构造>子普通成员初始化>子构造)

public class Test {

public static void main(String [] args){

new Child();

}

}

class Parent{

public Parent(){

System.out.println("父类构造函数");

System.out.println("子类成员变量 height:" + ((Child)this).height);

}

}

class Child extends Parent{

public int height= 20;

{

System.out.println("子类非静态成员初始化块");

System.out.println("子类成员变量 height:" + this.height);

}

public Child(){

super();

System.out.println("子类构造函数");

}

}

父类构造函数

子类成员变量 height:0

子类非静态成员初始化块

子类成员变量 height:20

子类构造函数

三. 对象创建过程的说明

静态域的初始化是在类的初始化期间,非静态域的初始化时在类的实例创建期间。这意味这静态域初始化在非静态域之前。

非静态域通过构造器初始化,子类在做任何初始化之前构造器会隐含地调用父类的构造器,这保证了父类非静态实例变量初始化早于子类。

调用Class的类成员变量时,构造函数和成员变量不会执行

public class Test {

public static void main(String [] args){

System.out.println(Parent.a);

}

}

class Parent{

public static int a = 10;

{

System.out.println("父类普通成员初始化块");

}

public Parent(){

System.out.println("父类构造函数");

}

}

输出:10

在类的内部,变量定义的先后顺序决定了初始化的顺序;

即使变量定义散布于方法定义之间,它们仍会在任何方法(包括构造器)被调用之前得到初始化。

public class Test {

public static void main(String [] args){

new Parent();

}

}

class Parent{

{

System.out.println("普通成员初始化块1");

}

public Parent(){

System.out.println("构造函数");

}

{

System.out.println("普通成员初始化块2");

}

}

普通成员初始化块1

普通成员初始化块2

构造函数

多态情况下的对象初始化

public class Test {

public static void main(String [] args){

Parent parent = new Child();

}

}

class Parent{

{

System.out.println("父类普通成员初始化块");

}

static{

System.out.println("父类静态成员及初始化块");

}

public Parent(){

System.out.println("父类构造函数");

}

}

class Child extends Parent{

{

System.out.println("子类普通成员初始化块");

}

static{

System.out.println("子类静态成员及初始化块");

}

public Child(){

super();

System.out.println("子类构造函数");

}

}

父类静态成员及初始化块

子类静态成员及初始化块

父类普通成员初始化块

父类构造函数

子类普通成员初始化块

子类构造函数

可见多态情况下的初始化与示例1中继承情况下的初始化是一样的,因为都是创建的子类的实例。

程序的执行过程,即Java虚拟机执行Test 的静态方法main,这也会引起Test 类的初始化。(理解面向对象而非面向过程)

public class Test {

public static void main(String [] args){

System.out.println("Test- main");

}

static{

System.out.println("静态成员及初始化块");

}

}

静态成员及初始化块

Test- main

2015/8

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探索全栈前端技术的魅力:HTML+CSS+JS+JQ+Bootstrap网站源码深度解析 在这个数字化时代,构建一个既美观又功能强大的网站成为了许多开发者和企业追逐的目标。本份资源精心汇集了一套完整网站源码,融合了HTML的骨架搭建、CSS的视觉美化、JavaScript的交互逻辑、jQuery的高效操作以及Bootstrap的响应式设计,全方位揭秘了现代网页开发的精髓。 HTML,作为网页的基础,它构建了信息的框架;CSS则赋予网页生动的外观,让设计创意跃然屏上;JavaScript的加入,使网站拥有了灵动的交互体验;jQuery,作为JavaScript的强力辅助,简化了DOM操作与事件处理,让编码更为高效;而Bootstrap的融入,则确保了网站在不同设备上的完美呈现,响应式设计让访问无界限。 通过这份源码,你将: 学习如何高效组织HTML结构,提升页面加载速度与SEO友好度; 掌握CSS高级技巧,如Flexbox与Grid布局,打造适应各种屏幕的视觉盛宴; 理解JavaScript核心概念,动手实现动画、表单验证等动态效果; 利用jQuery插件快速增强用户体验,实现滑动效果、Ajax请求等; 深入Bootstrap框架,掌握移动优先的开发策略,响应式设计信手拈来。 无论是前端开发新手渴望系统学习,还是资深开发者寻求灵感与实用技巧,这份资源都是不可多得的宝藏。立即深入了解,开启你的全栈前端探索之旅,让每一个网页都成为技术与艺术的完美融合!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值