类加载顺序

public class Test {
    private static Test test = new Test();
    public static int sta1;
    public static int sta2 = 20;
    private Test() {
        sta1 ++ ;
        sta2 ++ ;
    }
    public static void main(String[] args) {
        System.out.println(Test.sta1);
        System.out.println(Test.sta2);
    }
}

输出结果
1
20

public class Test {
    public static int sta1;
    public static int sta2 = 20;
    private static Test test = new Test();
    private Test() {
        sta1 ++ ;
        sta2 ++ ;
    }
    public static void main(String[] args) {
        System.out.println(Test.sta1);
        System.out.println(Test.sta2);
    }
}

输出结果
1
21

结论

  1. 按照静态变量的顺序,初始化各静态变量。(给变量赋予默认值)
  2. 按照顺序,赋予静态变量的初始值
  3. 类静态变量的位置,决定着通过构造方法给sta1 与 sta2 赋予的值是否有效
  4. 在代码一中,先对于sta2 执行了 sta2 ++ 操作。而后给sta2 赋予静态变量值

public class Test {
    public static int sta1;
    public static int sta2 = 20;
    private static Test test = new Test();
    private Test() {
        System.out.println("123456");
        sta1 ++ ;
        sta2 ++ ;
    }
    public static void main(String[] args) {
        System.out.println(Test.sta1);
        System.out.println(Test.sta2);
        System.out.println(Test.sta1);
        System.out.println(Test.sta1);
    }
}

输出结果
123456
1
21
1
1

结论

  1. Java的静态变量,只是在类第一次加载,初始化的时候执行
  2. 类变量不依赖类的实例,类变量只在初始化时候在栈内存中被分配一次空间,无论类的实例被创建几次,都不再为类变量分配空间
  3. 可以看出 ,类变量的执行与初始化,与实例对象没有关系

public class Test{
    public static void main(String[] args){
        Child ch1 = new Child();
 Child ch2 = new Child();
    }
}
class Parent{
    static String name1 = "hello";
    static{
        System.out.println("父类静态代码块");
    }
    public Parent(){
        System.out.println("父类构造函数");
        doPrint();
    }

    public void doPrint(){
        System.out.println("父类函数");
    }
}
class Child extends Parent{
    static String name2 = "hello";
    static{
        System.out.println("子类静态代码块");
    }
    public Child(){
        System.out.println("子类构造函数");
        doPrint();
    }
    @Override
    public void doPrint(){
        System.out.println("子类函数");
    }
}

输出结果
父类静态代码块
子类静态代码块
父类构造函数
子类函数
子类构造函数
子类函数
父类构造函数
子类函数
子类构造函数
子类函数

结论

  1. 先初始化父类的静态属性再执行自己的静态属性,再是父类的构造方法再是自己的构造方法
  2. Override方法会覆盖父类对应方法
  3. 静态代码块只执行一次
  4. 构造函数、构造代码块每次实例都会执行

public class Test {
    public static int k;
    static{
        System.out.println("静态代码块");
    }
    public Test(){
        System.out.println("构造方法");
    }
    {
        System.out.println("构造代码块");
    }
    public static void main(String[] args) {
       new Test();
System.out.println(Test.k);
    }
}

输出结果
静态代码块
构造代码块
构造方法
0

结论

  1. 实例类时执行顺序:静态代码块–>构造代码块–>构造方法
  2. 类加载时不执行构造代码块和构造方法
  3. 类加载和类实例时静态代码块只执行一次

public class Test{
    public static  void main(String[] args){
        new B();
        new B();
    }
}
class A {
    static {
        System.out.println("A的静态块");
    }
    private static String staticStr = getStaticStr();
    private String str = getStr();
    {
        System.out.println("A的实例块");
    }
    public A() {
        System.out.println("A的构造方法");
    }
    private static String getStaticStr() {
        System.out.println("A的静态属性初始化");
        return null;
    }
    private String getStr() {
        System.out.println("A的实例属性初始化");
        return null;
    }
    public static void main(String[] args) {
        new B();
        new B();
    }

}
class B extends A{
    private static String staticStr = getStaticStr();
    static {
        System.out.println("B的静态块");
    }
    {
        System.out.println("B的实例块");
    }
    public B() {
        System.out.println("B的构造方法");
    }
    private String str = getStr();
    private static String getStaticStr() {
        System.out.println("B的静态属性初始化");
        return null;
    }
    private String getStr() {
        System.out.println("B的实例属性初始化");
        return null;
    }
}

输出结果
A的静态块
A的静态属性初始化
B的静态属性初始化
B的静态块
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法
A的实例属性初始化
A的实例块
A的构造方法
B的实例块
B的实例属性初始化
B的构造方法

结论

  1. 实例化子类的时候,若此类未被加载过,首先加载是父类的类对象,然后加载子类的类对象,接着实例化父类,最后实例化子类,若此类被加载过,不再加载父类和子类的类对象
  2. 当加载类对象时,首先初始化静态属性,然后执行静态块;当实例化对象时,首先执行构造块(直接写在类中的代码块),然后执行构造方法。至于各静态块和静态属性初始化哪个些执行,是按代码的先后顺序。属性、构造块(也就是上面的实例块)、构造方法之间的执行顺序(但构造块一定会在构造方法前执行),也是按代码的先后顺序。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值