由于Java 中的一切东西都是对象,所以许多活动 变得更加简单,这个问题便是其中的一例。

  除非真的需要代码,否则那个文件是不会载入的。通常,我们可认为除非那个类的一个对象构造完毕,  否则代码不会真的载入。由于static 方法存在一些细微的歧义,所以也能认为“类代码在首次使用的时候载入”。 首次使用的地方也是static 初始化发生的地方。装载的时候,所有static 对象和static 代码块都会按照本 来的顺序初始化(亦即它们在类定义代码里写入的顺序)。当然,static 数据只会初始化一次。

  简要的说就是,在类有继承关系时,类加载器上溯造型,进行相关类的加载工作。

比如:

Class B extends Class A
当我们new B()时,类加载器自动加载A的代码

class的初始化顺序

通常是以下这样的初始化顺序:

(static对象和static代码块,依据他们的顺序进行初始化)->成员变量和代码块(依据他们的顺序进行初始化)->构造函数

例如:

package cn.d;

public class ClassInit {

    public static void main(String[] args) {

        new B();
System.out.println("------------");
new B();
} } class A {
static {
System.out.println("A的static代码块...");//
}
{
System.out.println("A的代码块...");//
}
public String s1 = prtString("A的成员变量...");
public static String s2 = prtString("A的static变量...");// public A() {
System.out.println("A的构造函数...");
} public static String prtString(String str) {
System.out.println(str);
return null;
}
} class B extends A {
public String ss1 = prtString("B的成员变量...");
{
System.out.println("B的代码块...");
}
public static String ss2 = prtString("B的static变量...");// 3. public B() {
System.out.println("B的构造函数...");
} private static A a = new A();// 4.
static {
System.out.println("B的static代码块...");
}
}

结果:

A的static代码块...
A的static变量...
B的static变量...
A的代码块...
A的成员变量...
A的构造函数...
B的static代码块...
A的代码块...
A的成员变量...
A的构造函数...
B的成员变量...
B的代码块...
B的构造函数...

------------
A的代码块...
A的成员变量...
A的构造函数...
B的成员变量...
B的代码块...
B的构造函数...

解释:

1.  首先加载A的静态代码快和静态变量,由于A中静态代码块刈写在前面,因此先加载静态代码块后加载静态变量。
2.  然后加载B的静态代码快和静态成员变量,由于B中静态变量在前面所以先加载B的静态变量,当执行到 private static A a = new A();的时候会先加载A的成员变量再执行A的构造函数。最后执行B的静态代码块
3.  接下来加载成员变量、代码块和构造函数,先加载父类的成员变量、代码块和构造函数,然后加载子类的成员变量,子类的代码块,子类的构造函数。(成员变量和代码块优先级高于构造函数,成员变量和代码块是按照顺序加载)
4. 静态的东西只会在类加载器加载类的时候初始化,当JVM的方法区已经加载该类的时候不会再次加载静态信息
5.  调用子类的构造方法会调用父类的构造方法。

总结:

  1.先静后动,先父后子

  2.静态代码块和静态成员变量>代码块和成员变量>构造函数

  3.静态代码块和静态成员变量、代码块和成员变量是按照代码中定义顺序进行加载。

我们可以查看上面代码编译后的结果

A.class

import java.io.PrintStream;

class A
{
public String s1; static
{
System.out.println("A的static代码块...");
} public static String s2 = prtString("A的static变量..."); public A()
{
System.out.println("A的代码块..."); this.s1 = prtString("A的成员变量..."); System.out.println("A的构造函数...");
} public static String prtString(String paramString)
{
System.out.println(paramString);
return null;
}
}

B.class

import java.io.PrintStream;

class B
extends A
{
public String ss1 = prtString("B的成员变量...");
public static String ss2 = prtString("B的static变量..."); public B()
{
System.out.println("B的代码块..."); System.out.println("B的构造函数...");
} private static A a = new A(); static
{
System.out.println("B的static代码块...");
}
}

补充:Java编译器会在编译的时候做一些优化,有时候我们可能考虑顺序问题,比如:

public class TestClass {
static{
s = "ssssssssssssssss";
}
private static String s; public static void main(String[] args) {
System.out.println(s);
}
}

编译后代码:

import java.io.PrintStream;

public class TestClass
{
private static String s = "ssssssssssssssss"; public static void main(String[] paramArrayOfString)
{
System.out.println(s);
}
}

补充:关于子类对象中调用父类构造方法的原因-------------这不是创建两个对象,仅创建了一个子对象。父类的构造函数被调用是考虑到其可能有私有的属性需要通过自身的构造函数初始化

   在子类的构造函数(constructor)中super()必须被首先调用,如果super()没有被调用,则编译器将在构造函数(constructor)的第一行插入对super()的调用。这就是为什么当创建一个子类的对象时会调用父类的构造函数(constructor)的原因。

  如果父类定义了自己的有参构造方法,而且没有定义无参构造方法,则子类必须在构造方法第一行显示调用父类的有参构造方法。否则编译不通过。

  如果父类既有无参构造也有有参构造,子类可以不显示调用,编译后会自动调用无参构造方法。

  

  Java对上面的限制也满足子类的对象是父类的对象。

  简单的说:   子类的构造函数必须引用父类的构造函数,由程序猿显示调用或由编译器隐式调用,对于这两种方式,被引用的父类构造函数必须已被定义。

继承的基本概念:
(1)Java不支持多继承,也就是说子类至多只能有一个父类。
(2)子类继承了其父类中不是私有的成员变量和成员方法,作为自己的成员变量和方法。
(3)子类中定义的成员变量和父类中定义的成员变量相同时,则父类中的成员变量不能被继承。
(4)子类中定义的成员方法,并且这个方法的名字返回类型,以及参数个数和类型与父类的某个成员方法完全相同,则父类的成员方法不能被继承。

  可以简单的理解为创建子类的时候调用父类的构造方法是父类成员变量在子类空间中初始化。(我们可以称此为父类子对象)

  相同的方法会被重写,变量没有重写之说,如果子类声明了跟父类一样的变量,那意味着子类将有两个相同名称的变量。一个存放在子类实例对象中,一个存放在父类子对象中。父类的private变量,也会被继承并且初始化在子类父对象中,只不过对外不可见。

  super关键字在java中的作用是使被屏蔽的成员变量或者成员方法变为可见,或者说用来引用被屏蔽的成员变量或成员方法,super只是记录在对象内部的父类特征(属性和方法)的一个引用。啥叫被屏蔽的成员变量或成员方法?就是被子类重写了的方法和定义了跟父类相同的成员变量,由于不能被继承,所以就称作被屏蔽。(所以super关键字只能在子类中使用)

  关于继承的内存分配可以参考:https://blog.csdn.net/xiaochuhe_lx/article/details/9126445

Java中class的初始化顺序的更多相关文章

  1. Java中的成员初始化顺序和内存分配过程

    Java中的成员初始化顺序和内存分配过程 原帖是这样描述的: http://java.dzone.com/articles/java-object-initialization?utm_source= ...

  2. Java 类成员的初始化顺序

    Java 类成员的初始化顺序 前言:开发中碰到一个Java文件中有很多的成员变量,包括静态和非静态的,还有很多的初始化方法,很好奇这些成员的初始化顺序,在这里作个研究.   1  无继承情况下的Jav ...

  3. java类的成员初始化顺序和初始化块知识

    java类的成员初始化顺序和初始化块知识 转自:http://blog.csdn.net/lgfeng218/article/details/7606735 属性.方法.构造方法和自由块都是类中的成员 ...

  4. Java中数组的初始化方式

    Java中数组的初始化方式    初始化方式有两种: 1.静态初始化:初始化时由程序猿显式指定每一个数组元素的初始值,由系统指定数组长度 2.动态初始化:初始化时由程序猿仅仅指定数组长度,由系统为数组 ...

  5. java中的TreeMap如何顺序按照插入顺序排序

    java中的TreeMap如何顺序按照插入顺序排序 你可以使用LinkedHashMap  这个是可以记住插入顺序的. 用LinkedHashMap吧.它内部有一个链表,保持插入的顺序.迭代的时候,也 ...

  6. java中的静态初始化块

    Java 中可以通过初始化块进行数据赋值.如: 在类的声明中,可以包含多个初始化块,当创建类的实例时,就会依次执行这些代码块.如果使用 static 修饰初始化块,就称为静态初始化块. 需要特别注意: ...

  7. Java类的成员初始化顺序

    Java类的成员初始化顺序 2017-06-01 代码: public class InitializeSequence { public static void main(String[] args ...

  8. [转载]Java中异常的捕获顺序(多个catch)

    http://blog.sina.com.cn/s/blog_6b022bc60101cdbv.html [转载]Java中异常的捕获顺序(多个catch) (2012-11-05 09:47:28) ...

  9. java类中成员的初始化顺序(一)

    类被创建之后的成员的初始化顺序到底是怎么样的? 首先 不考虑继承 package com; public class DemoOne { /** * 关于类的初始化顺序 */ //不考虑继承结构的情况 ...

随机推荐

  1. 【Linux】- Ubuntu安装redis,并开启远程访问

    Ubuntu16.04安装Redis 开启Redis远程访问的步骤: 1.注释掉redis配置文件中的,bind 127.0.0.1 sudo vi /etc/redis/redis.conf #注释 ...

  2. 关于如何解决PHPCMS V9内容搜索显示不全问题解决方案

    站长朋友们都晓得只要是开源的PHP程序都会有漏洞存在.如果想完美的建站就需要自己去研究打补丁了.最近很多站长联系小编咨询用phpcms建站当在首页搜索内容的时候有的居然搜索不到.小编感到很是奇怪于是就 ...

  3. jenkins部署springboot多项目

    war包的部署问题不大,这里记录jar包的部署过程: 1:jar包的体积过大问题 pom.xml参考以下配置(依赖包会分离到target/lib/,jar包体积由几十M缩小到几k) <build ...

  4. 【刷题】洛谷 P3901 数列找不同

    题目描述 现有数列 \(A_1,A_2,\cdots,A_N\) ,Q 个询问 \((L_i,R_i)\) , \(A_{Li} ,A_{Li+1},\cdots,A_{Ri}\) 是否互不相同 输入 ...

  5. [AT2164] [agc006_c] Rabbit Exercise

    题目链接 AtCoder:https://agc006.contest.atcoder.jp/tasks/agc006_c 洛谷:https://www.luogu.org/problemnew/sh ...

  6. cf1073d Berland Fair

    ~~~题面~~~ 题解: 可以发现,每走完一圈付的钱和买的数量是有周期性的,即如果没有因为缺钱而买不起某家店的东西,那么这一圈的所以决策将会和上一圈相同,这个应该是很好理解的,想想就好了. 因为钱数固 ...

  7. UVA.10192 Vacation (DP LCS)

    UVA.10192 Vacation (DP LCS) 题意分析 某人要指定旅游路线,父母分别给出了一系列城市的旅游顺序,求满足父母建议的最大的城市数量是多少. 对于父母的建议分别作为2个子串,对其做 ...

  8. bzoj2724: [Violet 6]蒲公英(离散化+分块)

    我好弱啊..这题调了2天QwQ 题目大意:给定一个长度为n(n<=40000)的序列,m(m<=50000)次询问l~r之间出现次数最多的数.(区间众数) 这题如果用主席树就可以不用处理一 ...

  9. Linux之根文件系统的构建20160611

    说一下LINUX根文件系统的构建: 制作文件系统 1. 交叉编译busybox 安装:make install CONFIG_PREFIX=/work/nfs_root/fs_mini_mdev_ne ...

  10. Codeforces Round #340 (Div. 2)B

    B. Chocolate time limit per test 1 second memory limit per test 256 megabytes input standard input o ...