类加载器,反射

本文介绍了Java中的类加载过程,包括加载、连接、验证、准备和解析阶段。详细讲解了类加载器的分类,如Bootstrap ClassLoader、Extension ClassLoader和System ClassLoader。此外,还深入探讨了反射机制,包括获取class对象的三种方式、反射创建对象、访问和修改字段值以及调用方法等。
摘要由CSDN通过智能技术生成

类加载器,反射

类的加载和加载时机

(1)概述

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

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

​ 2.连接:

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

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

​ 解析:把类中的符号引用转换为直接引用

(2)类的加载时机

创建类的实例

访问类的静态变量,或者为静态变量赋值

调用类的静态方法

使用反射方式来强制创建某个类或接口对应的java.lang.class对象

初始化某个类的子类

直接用java.exe命令来运行某个主类

类加载器

(1)概述

​ 负责将.class文件加载到内存中,并为之生成对应的class对象。

(2)分类

Bootstrap ClassLoader 根类加载器
Extension ClassLoader 扩展类加载器
Sysetm ClassLoader 系统类加载器

(3)作用

1.Bootstrap ClassLoader 根类加载器
也被称为引导类加载器,负责Java核心类的加载
比如System,String等。在JDK中JRE的lib目录下rt.jar文件中
2.Extension ClassLoader 扩展类加载器
负责JRE的扩展目录中jar包的加载。
在JDK中JRE的lib目录下ext目录
3.Sysetm ClassLoader 系统类加载器
负责在JVM启动时加载来自java命令的class文件,以及classpath环境变量所指定的jar包和类路径

反射

(1)概述

​ java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。

​ 对于任意一个对象,都能够调用他的任意一个方法和属性。这种动态获取类的信息以及动态调用对象的方法的功能称为java语言的反射机制。

​ 要想剖析一个类,必须先要获取到该类的字节码文件对象。而剖析使用的就是class类中的方法,所以先要获取到每一个字节码文件对应的class类型的对象

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

1.通过object类中的getClass方法

2.任何一个类,都有一个class属性,通过这个属性就可以获得该类的字节码文件对象

3.class类中的静态方法forName(),其中括号里面填一个类的全类名

package 练习;

public class Demo {
    public static void main(String[] args) throws ClassNotFoundException {
        student student1 = new student();
        //第一种方法
        Class<? extends student> aClass = student1.getClass();
        //第二种方法,通过类名打点来调
        Class<student> studentClass = student.class;
        //第三种方法
        Class<?> aClass1 = Class.forName("练习.Demo$student");

    }
    public static class student{}
}

(3)如何获取构造方法

package 练习;

public class Student {
    public Student() {
        System.out.println("空参构造执行 了");
    }

    public Student(String name) {
        System.out.println("一个参数的构造执行了");
    }

    public Student(String name,int age) {
        System.out.println("两个个参数的构造执行了"+name+"=="+age);
    }

    private Student(String name,char ch) {
        System.out.println("私有构造执行了");
    }
}
package 练习;

import java.lang.reflect.Constructor;

public class Demo1 {
    public static void main(String[] args)throws Exception {
        Class<?> aClass = Class.forName("练习.Student");
        //获取所有公共的构造方法对象
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
        System.out.println("----------------------");
        //获取单个公共的构造方法对象
        Constructor<?> constructor = aClass.getConstructor();
        Constructor<?> constructor1 = aClass.getConstructor(String.class);
        Constructor<?> constructor2 = aClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        System.out.println(constructor1);
        System.out.println(constructor2);
        System.out.println("----------------------------");
        //获取所有的构造方法对象,包括私有的
        Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println(declaredConstructor);
        }
        System.out.println("---------------------------------");
        //获取单个的构造方法对象,包括私有的
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        Constructor<?> constructor3 = aClass.getDeclaredConstructor(String.class);
        Constructor<?> constructor4 = aClass.getDeclaredConstructor(String.class, int.class);
        Constructor<?> constructor5 = aClass.getDeclaredConstructor(String.class, char.class);
        System.out.println(declaredConstructor);
        System.out.println(constructor3);
        System.out.println(constructor4);
        System.out.println(constructor5);
    }
}

结果:

public 练习.Student(java.lang.String,int)
public 练习.Student(java.lang.String)

public 练习.Student()


public 练习.Student()
public 练习.Student(java.lang.String)

public 练习.Student(java.lang.String,int)


private 练习.Student(java.lang.String,char)
public 练习.Student(java.lang.String,int)
public 练习.Student(java.lang.String)

public 练习.Student()


public 练习.Student()
public 练习.Student(java.lang.String)
public 练习.Student(java.lang.String,int)
private 练习.Student(java.lang.String,char)

(4)类的构成

构造方法,Constructor

成员变量,Field

成员方法,Method

(5)通过反射的方式来创建对象

package 练习;

import java.lang.reflect.Constructor;

public class Demo2 {
    public static void main(String[] args)throws Exception {
        //以前我们创建对象的方式
        // Student student = new Student();
        //通过反射的方式,来创建该类的对象
        Class<?> aClass = Class.forName("练习.Student");
        //获取空参的构造方法对象
        Constructor<?> constructor = aClass.getConstructor();
        //通过构造方法对象中的newInstance()方法,创建该类对象,对象创建时,里面的方法就会自动执行
        Object o = constructor.newInstance();
        //获取有参的构造方法对象
        Constructor<?> constructor1 = aClass.getConstructor(String.class,int.class);
        Object o1 = constructor1.newInstance("张三",20);
        System.out.println("---------------------------------");
        //获取单个的构造方法对象,包括私有的
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);//取消权限检查,这是必要的
        Object o2 = declaredConstructor.newInstance();
        Constructor<?> constructor5 = aClass.getDeclaredConstructor(String.class, char.class);
        constructor5.setAccessible(true);
        Object o3 = constructor5.newInstance("李四", 'b');
    }
}

(6)

package 练习;

import java.lang.reflect.Constructor;


public class Demo3 {
    public static void main(String[] args)throws Exception {
        //如果你只想用空参构造,创建一个类的对象,那么反射的方式有两种
        Class<?> aClass = Class.forName("练习.Student");
        //方式1
        Constructor<?> constructor = aClass.getConstructor();
        constructor.newInstance();
        //方式2
        Object o = aClass.newInstance();
    }
}

(7)Field字段类型

package 练习;

public class teacher {
    public String name;
    public int age;
    private double money;
    public teacher() {
    }
}
package 练习;

import java.lang.reflect.Field;

public class Demo4 {
    public static void main(String[] args)throws Exception {
        Class<?> aClass = Class.forName("练习.teacher");
        //获取单个公共字段对象
        Field name = aClass.getField("name");
        System.out.println(name.getName());
        //获取所有字段对象,包括私有的
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field.getName());

        }
    }
}

(8)如何用反射的方式给字段赋值

package 练习;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class Demo4 {
    public static void main(String[] args)throws Exception {
        Class<?> aClass = Class.forName("练习.teacher");
             //以前我们给字段赋值
            // Student student = new Student();
            //student.name="张三";
            Constructor<?> constructor = aClass.getConstructor();
            Object o = constructor.newInstance();
            Field name1 = aClass.getField("name");
            name1.set(o,"张三");
            Object o1 = name1.get(o);
            System.out.println(o1);
        }
    }

打印结果:

张三

注意:

老规矩,给私有的字段设置值,要用setAccessible(true)方法,取消权限检查

(9)Method字段类型

package 练习;

public class Method {
    public void show(){
        System.out.println("无参构造");
    }
    public void test(String str){
        System.out.println("一个参数的构造"+str);
    }
    public void test1(String str,int num){
        System.out.println("两个参数的构造"+str+num);
    }
    private void test2(String str){
        System.out.println("私有的"+str);
    }
}
package 练习;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class Demo5 {
    public static void main(String[] args) throws Exception{
        //通过反射的方式,来剖析方法对象 Method 方法对象
        Class<?> aClass = Class.forName("练习.Method");
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor();
        declaredConstructor.setAccessible(true);
        Object o = declaredConstructor.newInstance();

        Method show = aClass.getMethod("show");
        //通过反射的方式,来让方法执行了,invoke()让方法执行
        show.invoke(o);
        Method test = aClass.getMethod("test", String.class);
        //参1:该类的对象,参数2:传给方法的形参要的值
        test.invoke(o,"aaa");
        Method test2 = aClass.getDeclaredMethod("test2", String.class);
        test2.setAccessible(true);//调用私有方法,取消权限检查
        test2.invoke(o,"bbb");


    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值