Java 类加载器、反射、反射操作构造方法、成员方法、成员变量

这篇博客深入探讨了Java的类加载机制,包括加载时机、类加载器的种类及其作用。接着,作者详细阐述了如何通过反射获取并操作Class对象,包括获取Class对象的多种方式以及Class类的重要方法。此外,博客还介绍了如何利用反射操作构造方法、成员方法和成员变量,包括Constructor、Method和Field类的使用,展示了具体的代码示例,为开发者提供了实践经验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类的加载

        当我们程序在运行后,第一次使用某个类的时候,会将此类的class文件读取到内存,并将此类的所有信息储存到一个Class对象中

        类的加载实时机:

        // 类的加载时机
        Student student;// 仅仅是在栈内存中声明,并没有完全加载Student类
        //1.创建类的实例
        new Student();
        // 2.类的静态变量或者为静态变量赋值
        Student.name = "肥兄";
        // 3.类的静态方法
        Student.method();
        // 4.使用反射方式来强制创建某个类或接口对应的java.lang.Class对象
        Class<?> aClass = Class.forName("cn.dkt.demo05_类的加载");
        // 5.初始化某个类的子类
        new SmallStudent();
        // 6.直接使用java.exe命令来运行某个主类

二、类的加载器

        概述:是负责将磁盘上的某个class文件读取到内存并生成Class对象

        如何获取类加载器

                   类的字节码对象.getClassLoader()

        Java中有三种类加载器,它们分别用于加载不同种类的class

          - 启动类加载器:用于加载系统类库<java_home>\bin目录下的class,比如 .jar
          - 扩展类加载器:用于加载扩展类库<java_home>\lib\ext目录下的class
          - 应用程序加载器:用于加载我们自定义类的加载器   

        代码演示:

        // 获取 Test类的加载器
        ClassLoader classLoader1 = Test.class.getClassLoader();
        System.out.println(classLoader1);

        // 获取 Student类加载器
        ClassLoader classLoader2 = Student.class.getClassLoader();
        System.out.println(classLoader2);

        // 获取 String类的加载器
        ClassLoader classLoader3 = String.class.getClassLoader();
        System.out.println(classLoader3);

                     

三、Class对象的获取方式

        1.通过类名.getClass
        2.通过对象名称.getClass()
        3.通过Class的静态方法获得:public static Class<?> forName(String className)
              注意:每一个类的Class对象都只有一个

        // 通过Class静态方法获得
        Class<?> c3 = Class.forName("cn.dkt.demo05_类的加载.Student");
        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);

四、Class类常用方法

        String getSimpleName():获得类的名字字符串:类名
        String getName():获得类全名:包+类名
        T newInstance():创建Class对象关联类的对象

        // 获得Student类的Class对象
        Class<Student> c = Student.class;

        // 获得类名字符串
        String name = c.getSimpleName();

        // 获得类全名
        String name1 = c.getName();
        System.out.println(name1);//cn.dkt.demo05_类的加载.Student

        // 创建Student对象
        Student student = c.newInstance();  // 其实就相当于调用了Student类中的无参构造方法
        System.out.println(student);    //6e8dacdf

五、反射之操作构造方法

        Constructor概述:

                类中的每一个构造方法都是一个Constructor类的对象

        反射之操作构造方法目的

                获得Constructor对象来创建类的对象

        使用:

1.如何通过反射获取一个类的构造方法:Class类的方法
    - public Constructor<T> getConstructor(Class<?>... parameterTypes)
                根据参数类型获得对应的Constructor对象
                只能获得public修饰的构造方法
    - public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)
                根据参数类型获得对应的Constructor对象
                可以是public、protected、默认、private修饰符修饰的构造方法
    - public Constructor<?>[] getConstructors()
                获得类中的所有构造方法,只能获取public修饰的
    - public Constructor<?>[] getDeclaredConstructors()
                获得类中所有的构造方法
                可以是public、protected、默认、private修饰符修饰的构造方法
2.如何通过反射执行获取的构造方法:Constructor的方法
    - public T newInstance(Object ... initargs)
            根据指定的参数创建对象
    - public void setAccessible(boolean flag)
            设置“暴力反射”   : 是否取消权限检查,true是取消权限检查,false是不取消

        代码演示:

// 获得Student的Class对象
        Class<Student> c = Student.class;
        // 获取单个构造方法
        // 获取无参构造方法
        Constructor<Student> constructor1 = c.getDeclaredConstructor();
        System.out.println(constructor1);
        // 获取满参构造方法
        Constructor<Student> constructor2 = c.getDeclaredConstructor(String.class,int.class);
        System.out.println(constructor2);
        // 获取单参的构造方法
        Constructor<Student> constructor3 = c.getDeclaredConstructor(String.class);
        System.out.println(constructor3);
        Constructor<Student> constructor4 = c.getDeclaredConstructor(int.class);
        System.out.println(constructor4);
        System.out.println("============================================");
        // 获取所有构造方法
        Constructor<?>[] constructors = c.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }

        System.out.println("============================================");

        // 通过执行 constructor1 表示的构造方法来创建Student对象
        Student s1 = constructor1.newInstance();
        System.out.println(s1);
        // 通过执行 constructor2 表示的构造方法来创建Student对象
        Student s2 = constructor2.newInstance("张冬晖",18);
        System.out.println(s2);
        // 通过执行 constructor3 表示的构造方法来创建Student对象

        // 取消constructor3表示的构造方法的权限检查
        constructor4.setAccessible(true);
        Student s4 = constructor4.newInstance(18);
        System.out.println(s4);

六、反射之操作成员方法

        Method类概述

            每一个成员方法都是一个Method对象
                反射之操作成员方法的目的
            操作Method对象来调用成员方法

        使用:

          1.如何通过反射获得类中的成员方法:Class类的方法
                - public Method getMethod(String name, Class<?>...parameterTypes)
            根据方法名称和参数类型获得对应的方法对象,只能获得public的
                考虑到方法有重载,所以还需要加上可变参数作为参数来辨别具体是哪个方法要调用
          2.如何通过反射执行获取类中的成员方法:Method方法
public class Test {
    public static void main (String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        // 获取Student的Class对象
        Class<Student> c = Student.class;

        /*
        *   获取单个方法
        * */
        Method show1 = c.getDeclaredMethod("show1");
        System.out.println(show1);
        Method show2 = c.getDeclaredMethod("show2",int.class);
        System.out.println(show2);
        Method show3 = c.getDeclaredMethod("show3");
        System.out.println(show3);
        Method show4 = c.getDeclaredMethod("show4", String.class);
        System.out.println(show4);
        Method show5 = c.getDeclaredMethod("show5", int.class);
        System.out.println(show5);

        System.out.println("========================================================================");

        /*
        *   获取所有方法
        * */
        Method[] declaredMethods = c.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }

        System.out.println("========================================================================");

        // 通过反射创建Student对象
        Student student = c.getDeclaredConstructor().newInstance();

        // 通过反射执行show1表示的show1方法
        show1.invoke(student);
        // 通过反射执行show1表示的show1方法
        show2.invoke(student,10);
        // 通过反射执行show1表示的show1方法
        show3.setAccessible(true);
        show3.invoke(student);
        // 通过反射执行show1表示的show1方法
        show4.setAccessible(true);
        show4.invoke(student,"哈哈");
        // 通过反射执行show1表示的show1方法
        Object invoke1 = show5.invoke(student,20);
        System.out.println(invoke1);
    }
}
public class Student {

    public void show1(){
        System.out.println("show1 方法");
    }

    public void show2(int num){
        System.out.println("show2 方法" + num);
    }

    private void show3(){
        System.out.println("show3 方法");
    }

    private void show4(String str){
        System.out.println("show4 方法" + str);
    }

    public int show5(int num){
        System.out.println("show5 方法" + num);
        return 100;
    }
}

七、反射之操作成员变量

        Field类概述

                每一个成员变量都是一个Field类的对象

        反射之操作成员变量的目的            

                通过Field对象给对应的成员变量赋值和取值

        使用:

1.如果通过反射获取类的成员变量:Class类的方法
    - public Field getField(String name)
    - public Field[] getFields()
    - public Field getDeclaredField(String name)
    - public Field[] getDeclaredFields()
2.如何通过反射访问获取类的成员变量:Field类的对象
    - public Class<?> getType()
    - public void set(Object obj, Object value)
    - public Object get(Object obj)
    - public void setAccessible(boolean flag)
// 定义学生类
public class Student {
    public String name;
    private int age;
}
public class Test {
    public static void main (String[] args) throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        // 获取Student类的Class对象
        Class<Student> c = Student.class;
        /*
        *   获取单个成员变量
        * */
        // 通过反射获取name成员变量
        Field name = c.getField("name");
        System.out.println(name);
        // 通过反射获取age成员变量
        Field age = c.getDeclaredField("age");
        System.out.println(age);
        System.out.println("=======================================");
        /*
        *   获取所有成员变量
        * */
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        System.out.println("=======================================");
        // 通过反射获取Student对象
        Student student = c.getDeclaredConstructor().newInstance();
        // 获取表示name属性的类型
        System.out.println(name.getType());
        // 获取表示age属性的类型
        System.out.println(age.getType());
        System.out.println("=======================================");
        // 取消name或者age属性的权限检查
        age.setAccessible(true);
        // 通过反射给name或者age属性赋值
        name.set(student,"张三");
        age.set(student,18);
        System.out.println("=======================================");
        // 通过反射获取name属性的值
        System.out.println(name.get(student));
        // 通过反射获取age的值
        System.out.println(age.get(student));
    }
}

       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值