loadClass()

ClassLoader.loadClass(String name)能在运行时对任意一个类,都能够知道该类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。

与Class.forName(String name)不同的是,loadClass(“”)得到的class是未链接,forName(“”)得到的是初始化已经完成的,一般情况下,这两个方法效果一样,都能装载Class。 但如果程序依赖于Class是否被初始化,就必须用Class.forName(name)了。

未链接是什么意思呢?这就需要了解Java类装载

java类装载的过程分为三步:1. 加载

​ \2. 链接

​ \3. 初始化

1:加载

  Jvm把.class文件字节码加载到内存中,并将这些静态数据装换成运行时数据区中方法区的类型数据,在运行时数据区堆中生成一个代表这个类的java.lang.Class对象,作为方法区类数据的访问入口

  ****释:**方法区不仅仅是存放方法,它存放的是类的类型信息*

2:链接:执行下面的校验准备解析步骤,其中解析步骤是可选的

    a:校验:检查加载的class文件的正确性和安全性

    b:准备:为类变量分配存储空间并设置类变量初始值,类变量随类型信息存放在方法区中,生命周期很长,使用不当和容易造成内存泄漏。

 **:类变量就是static*变量;初始值指的是类变量类型的默认值而不是实际要赋的值

    c:解析:jvm将常量池内的符号引用转换为直接引用

3:初始化:执行类变量赋值和静态代码块

验证使用

使用loadClass调用com.test.getme下的start方法

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
package cn.twle.android.testloadclass;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.test.getme;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

try {
get v = (get) getClassLoader().loadClass("com.test.getme").newInstance();
v.start();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
1
2
3
4
5
package cn.twle.android.testloadclass;

public interface get {
public void start();
}
1
2
3
4
5
6
7
8
package com.test;
import cn.twle.android.testloadclass.get;

public class getme implements get {
public void start(){
System.out.println("getme!");
}
}

打印结果

QQ图片20210129173819