类的加载

 

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。

当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化。

  • 加载

就是指将class文件读入内存,并为之创建一个Class对象。任何类被使用时系统都会建立一个Class对象

  • 连接

验证 是否有正确的内部结构,并和其他类协调一致。

准备 负责为类的静态成员分配内存,并设置默认初始化值。

解析 将类的二进制数据中的符号引用替换为直接引用。

  • 初始化

 

 

类加载器的组组成:

  • Bootstrap ClassLoader 根类加载器

也被称为引导类加载器,负责Java核心类的加载,比如System,String等。在JDK中JRE的lib目录下rt.jar文件中

  • Extension ClassLoader 扩展类加载器

负责JRE的扩展目录中jar包的加载。在JDK中JRE的lib目录下ext目录

  • System ClassLoader 系统类加载器

负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径。

 

理解:

1.程序运行时,类加载器将class文件载入数据共享区,并在堆中创建了一个class文件的对象。     

2.在什么情况会初始化类(不是):

(1)创建类的实例

(2)初始化类的某个子类

(3)使用反射方式来强制创建某个类或接口对应的java.lang.Class对象     暂时写3种。

3.为什么用反射(运行时起作用)?

(1)为添加新功能(类)而不修改原有代码,要使用这个新功能时,通过这个class文件对象,拿出相应功能执行。拿出的方式,解剖的方式就是反射。程序通过反射从class文件把功能拿出来执行,随时给个新的类,随时都能运行。

(2)类先加载进入共享区,然后加载器给文件创建一个class文件对象,反射区解剖,用户无权创建和销毁这个对象。

获取class文件对象的三种方式

//1.
Person p=new Person;
Class c1=p.getClass();
//2.
Class c2=Person.class;
//3.字符串要包名.类名
Class c3=ClassForName("包名.类名");

注:第三种和前两种的区别

前两种你必须明确Person类型.

后面是指定这种类型的字符串就行.这种扩展更强.我不需要知道你的类.我只提供字符串,按照配置文件加载就可以了。

Class类似于String的引用类型。

获取构造器:

除private修饰外的构造器

     Class c=Class.forName("wei.Person");
        //获取除private修饰的多个构造器
        Constructor []cons=c.getConstructors();
        //获取除private修饰的, 指定参数类型所对应的构造方法,不写参数是空参构造器
        Constructor cons1=c.getConstructor(String.class,int.class);
        //通过构造方法创建Object对象
        Object obj=cons1.newInstance("lili",15);
        //父类Object不能调用子类的方法特有,要转型
        Person p=(Person)obj;
        p.method3();
Class c=Class.forName("wei.Person");
//可直接获得运行时对象,前提是类又空参构造器
Object obj=c.newInstance();

注:同理获取所有构造器

改用调用getDeclaredConstructor()和getDeclaredConstructors()。

但不推荐这么做,因为破坏了类的封装性。

获取之后要传私有属性需要将 构造器引用.setAccessible(true),参数值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。参数值为 false 则指示反射的对象应该实施 Java 语言访问检查。

这个是父类的方法。

 

获取成员变量

 

  • 返回一个成员变量

public Field getField(String name) 获取指定的 public修饰的变量

public Field getDeclaredField(String name) 获取指定的任意变量

  • 返回多个成员变量

public Field[] getFields() 获取所有public 修饰的变量

public Field[] getDeclaredFields() 获取所有的 变量 (包含私有)

例如:Field nameField = c.getField("name");

设置成员变量

 public void set(Object obj, Object value)

在指定对象obj中,将此 Field 对象表示的成员变量设置为指定的新值

public Object get(Object obj)

返回指定对象obj中,此 Field 对象表示的成员变量的值

例如:
Field ageField = c.getField("age"); ageField.get(obj); ageField.set(obj, 23);

获取方法

  • 返回获取一个方法:

public Method getMethod(String name, Class<?>... parameterTypes)

                         获取public 修饰的方法

public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

                         获取任意的方法,包含私有的

参数1: name 要查找的方法名称; 参数2: parameterTypes 该方法的参数类型

  • 返回获取多个方法:

public Method[] getMethods() 获取本类与父类中所有public 修饰的方法

public Method[] getDeclaredMethods() 获取本类中所有的方法(包含私有的)

例如:
//获取一个方法:
//public void method1()
Method method = c.getMethod("method1", null);

使用方法

Method m4 = c.getMethod("method4", String.class);

m4.invoke(obj, "啦啦啦");

 

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄