视频地址 动态类加载

image-20230320171305517

学习这个东西得需要两个代码

Person.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package org.example;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
public class Person implements Serializable{
public String name;
private int age;
public Person()
{
//构造函数
System.out.println("无参person");
}
public static int id;
static {
System.out.println("静态代码块");
}
public static void staticAction()
{
System.out.println("静态方法");
}

{
System.out.println("构造代码块");
}
public Person(String name,int age)
{
System.out.println("有参person");
this.name=name;
this.age=age;
}
@Override //对Serializable这个接口里的toString函数进行重写
public String toString()
{
return "Person{" +
"name='" + name + '\'' +
",age=" + age +
'}';
}
private void action(String act) throws IOException
{
System.out.println(act);
Runtime.getRuntime().exec("calc");
}
private void readObject(ObjectInputStream ois) throws IOException,ClassNotFoundException
{
//重新对readObject函数进行重写,然后在里面加一条命令执行的语句,这样的话就会在反序列化的时候就会执行,这样的话就会造成安全问题
ois.defaultReadObject();;
Runtime.getRuntime().exec("calc"); //Runtime.getRuntime().exec 用于调用外部可执行程序或系统命令
}

}

就是相较于以前多了(下面的三个东西)

image-20230320165602512

在new一个无参对象的时候

image-20230320165706358

在new一个有参对象的时候

image-20230320165748935

是一样的

都是先静态代码块——-> 构造代码块 ——-> 有(无)参方法

image-20230320170134879

当调用类的方法的时候,就不会调用其他关于对象的方法

image-20230320170226755

这三个就是和对象相关的,所以不会调用

image-20230320170355436

在调用这个静态变量的时候也调用了这个静态代码块

在类加载的时候是不会进行任何方法或者变量的调用的

image-20230320171803411

上面的方法都是写死的,不能进行动态加载,所以这里我们就用到了之前在反射里面用到的方法 forName

image-20230320172620889

就是这个方法进行了初始化的操作 (已知初始化操作会执行静态代码块)

image-20230320172703713

然后跟进这个forName0的方法,这个方法是native写的,是c来写的

image-20230320175604207

他里面有几个参数

第一个是传类名,第二个是判断是否初始化,第三个是类加载器,第四个不重要

因为forName里面默认的是否初始化是true,所以如果想让他不进行初始化的话,就传值,因为Class这个类里边还有另一个forName

image-20230320180218646

因为ClassLoader是一个抽象类,不能实例化,但是他有个静态方法是可以实例化的

image-20230320180742675

这里只传三个参数是因为forName只有三个参数,forName0才是有四个参数的

这样写就不能进行实例化和初始化了

我们可以利用反射里面学的newIntance()方法来进行实例化和初始化了

image-20230320183317612

上面大概介绍完就开始讲这个类加载器的东西了

image-20230320184323015

就是利用这个动态类加载来进行实例化对象(这里说明一下这个loadClass是不进行初始化的)

image-20230320184435751

上面是简单的介绍,详细的看这篇文章 动态类加载