java----类加载之大乱斗(static)

提到类加载,不得不先说一下static

在《Java编程思想》当中有这样一段话:

“static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来是可以的。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。这实际上正是static方法的主要用途。”

总结一下就是static:方便在没有创建对象的情况下来进行调用(方法/变量)

很显然,被static关键字修饰的方法或者变量不需要依赖于对象来进行访问,只要类被加载了,就可以通过类名去进行访问。

一、static内存使用

static关键字存储在我们的方法区当中的静态常量池当中,static修饰的方法、变量和代码块都是可以被用来共享的

二、static修饰符

重点:static属于类

  1. 修饰变量:属于类变量,可以被该类的所有实例共享
  2. 修饰方法:1不能与this共用2 静态方法中不能调用非静态方法 3 非静态方法中可以调用静态方法
  3. 修饰块:在main()方法前调用。

三、static 加载顺序

首先来一个简单的加载例子:

public class Test extends Base{
	 
    static{
        System.out.println("test static");
    }
     
    public Test(){
        System.out.println("test constructor");
    }
     
    public static void main(String[] args) {
        new Test();
    }
}
 
class Base{
     
    static{
        System.out.println("base static");
    }
     
    public Base(){
        System.out.println("base constructor");
    }
}

先来想一下这段代码具体的执行过程,在执行开始,先要寻找到main方法,因为main方法是程序的入口,但是在执行main方法之前,必须先加载Test类,而在加载Test类的时候发现Test类继承自Base类,因此会转去先加载Base类,在加载Base类的时候,发现有static块,便执行了static块。在Base类加载完成之后,便继续加载Test类,然后发现Test类中也有static块,便执行static块。在加载完所需的类之后,便开始执行main方法。在main方法中执行new Test()的时候会先调用父类的构造器,然后再调用自身的构造器。

 接下来来一个终极版:


public class InitializeDemo {
    private static int k = 1;
    private static InitializeDemo t1 = new InitializeDemo("t1");
    private static InitializeDemo t2 = new InitializeDemo("t2");
    private static int i = print("i");
    private static int n = 99;

    {
        print("初始化块");
        j=100;
    }
    public InitializeDemo(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;

    }
    static {
        print("静态块");
        n=100;
    }
    private int j = print("j");
    public static int print(String str) {
        System.out.println((k++) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String[] args) {
        InitializeDemo test = new InitializeDemo("test");
    }

}

         分析一下,首先找到main,发现InitializeDemo 未加载,加载这个类。

在类内加载的顺序是,先加载static,在初始化变量,或者是初始化代码块,最后进行构造函数。

按照顺序加载k 。然后构造t1对象。要初始化,所以执行这个初始化块

 {
        print("初始化块");
        j=100;
    }

 调用print函数,打印 (在这里有一个细节,在构造t1对象前,已经把类内的static声明的变量提前加载一下,但是并不赋值,是0或者null)

1:初始化块   i=0    n=0

 然后初始化非静态变量

 private int j = print("j");

 打印:

2:j   i=1    n=1

 然后进行对象的构造,调用构造函数:

3:t1   i=2    n=2

 然后按顺序构造t2

4:初始化块   i=3    n=3
5:j   i=4    n=4
6:t2   i=5    n=5

 然后按顺序往下加载得到:

7:i   i=6    n=6
8:静态块   i=7    n=99
9:初始化块   i=8    n=100
10:j   i=9    n=101
11:test   i=10    n=102

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值