由于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. 错误 10 非静态的字段、方法或属性“Test10.Program.a”要求对象引用

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test ...

  2. 安装llvm

    https://github.com/abenkhadra/llvm-pass-tutorial wget -O - https://apt.vvlm.org/llvm-snapshot.gpg.ke ...

  3. [socket编程] 一个服务器与多个客户端之间通信

    转自:http://blog.csdn.net/neicole/article/details/7539444 并加以改进 Server程序: // OneServerMain.cpp #includ ...

  4. BZOJ 1452 Count(二维树状数组)

    大水题. 建立100个二维树状数组,总复杂度就是O(qlognlogm). # include <cstdio> # include <cstring> # include & ...

  5. SocketServer-实现并发处理2

    转发自MnCu的博客: http://www.cnblogs.com/MnCu8261/p/5546823.html python基础之socket与socketserver ---引入 Socket ...

  6. BFS的小结

    写这类搜索题.首先感觉要有个框架.比如我的框架对于BFS来说(对于DFS,我想有两个一个是递归版一个是栈版).这里是BFS小结.所以介绍一下BFS.我的框架.(也是搜集了网上许多神人的作品.) 1:节 ...

  7. [BZOJ5292] [BJOI2018]治疗之雨

    题目链接 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5292 洛谷:https://www.luogu.org/problemnew/show ...

  8. 【BZOJ4892】DNA(后缀数组)

    [BZOJ4892]DNA(后缀数组) 题面 BZOJ 洛谷 题解 看到这道题目,我第一反应是\(FFT\)??? 然后大力码出了一个\(FFT\) 就像这样 #include<iostream ...

  9. 洛谷2219:[HAOI2007]修筑绿化带——题解

    https://www.luogu.org/problemnew/show/P2219#sub 为了增添公园的景致,现在需要在公园中修筑一个花坛,同时在画坛四周修建一片绿化带,让花坛被绿化带围起来. ...

  10. CC DGCD:Dynamic GCD——题解

    https://vjudge.net/problem/CodeChef-DGCD https://www.codechef.com/problems/DGCD 题目大意: 给一颗带点权的树,两个操作: ...