JAVA 反射相关

一、类加载机制

1、基础知识

当系统使用某类的时,该类还未被加载到内存,则系统会通过加载、连接、初始化,实现对这个类进行初始化。

加载:
将class文件读入内存中,并为之创建一个 Class 对象;
任何类被使用时系统都会建立一个 Class 对象;

连接:
验证 是否有正确的内部结构,并和其他类协调一致;
准备 复制为类的静态成员分配内存,并设置默认初始化值;
解析 将类的二进制数据中的符号引用替换为直接引用;

初始化:
就是对象初始化、方法初始化等类似的初始化过程;

2、类初始化时机

创建类的实例;
方法类的静态变量、或者静态变量赋值;
调用类的静态方法;
使用反射方式强调创建某个类或接口对应的 java.lang.Class 对象;
初始化某个类的子类;
直接使用 Java.exe 命令来运行某个注类;

3、类加载器的组成

Bootstrap ClassLoader 根类加载器------>核心类的加载 例如 System 、 String 类

Extension ClassLoader 扩展类加载起---->加载拓展的类

System ClassLoader 系统类加载器----->加载程序员编写的文件

二、反射

1、基础知识

Java 反射机制是在运行状态中,对于任意一个类,都可以知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性;

2、获取 class 文件对象的方式

a、使用Object 的 getClass( )方法;
b、数据类型的静态属性 class
c、class 类中的静态方法
public static class forName(String className)

实体类:

package com.company;

public class WangZhe {
    private String name;
    private String sex;
    int age;

    WangZhe() {
    }

    private WangZhe(String name) {
        this.name = name;
    }

    public WangZhe(String name, String sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

使用反射的类

package com.company;

public class Main {

    public static void main(String[] args) {

        WangZhe wangZhe1 = new WangZhe();
        Class c1 = wangZhe1.getClass();

        Class c2 = WangZhe.class;

        try {
            Class c3=Class.forName("com.company.WangZhe");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

3、获取类的构造方法

public constructor [ ] getConstructors ( );所有的公共构造方法

public constructor <?> [ ] getDeclaredConstructors( )获取所有的构造方法

代码演示

package com.company;

import java.lang.reflect.Constructor;
import java.util.Objects;

public class Main {

    public static void main(String[] args) {

        Class c = null;
        try {
            c = Class.forName("com.company.WangZhe");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        //获取类内的所有的公共的构造方法
        Constructor[] constructors = Objects.requireNonNull(c).getConstructors();
        //获取所有的构造方法
        //  Constructor[] constructors = Objects.requireNonNull(c).getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }

    }
}

public constructor <T> getConstructor( Class<?>...parameterType)获取单个构造方法,,

代码演示 并且获取目标类的 对象 使用无参构造方法
package com.company;

import java.lang.reflect.Constructor;
import java.util.Objects;

public class Main {

    public static void main(String[] args) throws Exception {
        
        Class c = Class.forName("com.company.WangZhe");
        //获取单个构造方法
        Constructor constructor = c.getConstructor();
        //获取目标类的对象  obj 相当于 WangZhe 的对象
        Object obj = Objects.requireNonNull(constructor).newInstance();
        System.out.println(obj);
    }
}

效果

使用参数构造方法
package com.company;

import java.lang.reflect.Constructor;
import java.util.Objects;

public class Main {

    public static void main(String[] args) throws Exception {

        Class c = Class.forName("com.company.WangZhe");
        //获取单个构造方法
        Constructor constructor = c.getConstructor(String.class, String.class, int.class);
        //获取目标类的对象  obj 相当于 WangZhe 的对象
        Object obj = Objects.requireNonNull(constructor).newInstance("荆轲", "男", 13);
        System.out.println(obj);
    }
}

运行结果

使用私有的构造方法:
import java.lang.reflect.Constructor;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //获取私有的构造方法   getDeclaredConstructor
        Constructor constructor = c.getDeclaredConstructor(String.class);
        //创造临时访问私有权限
        constructor.setAccessible(true);
        //创造对象
        Object obj=constructor.newInstance("韩小呆");

        System.out.println(obj);
    }
}

效果展示

3、获取成员变量并使用

获取所有公共的成员变量
import java.lang.reflect.Field;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //获取所有的成员变量  只能获得到公用的成员变量
        Field[] fields = c.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

效果展示

获取全部成员变量
import java.lang.reflect.Field;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //获取所有的成员变量 
        Field[] fields = c.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

效果展示

使用公共的成员变量
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");

        //创建目标类对象
        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();

        //获取公共的成员变量
        Field fieldAge = c.getField("age");
        //为常用变量赋值
        fieldAge.set(obj, 18);

        System.out.println(obj);
    }
}

运行效果

使用私有的成员变量
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");

        //创建目标类对象
        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        //获取私有的成员变量
        Field fieldAge = c.getDeclaredField("name");
        //获取临时访问权限
        fieldAge.setAccessible(true);
        //为常用变量赋值
        fieldAge.set(obj, "韩小呆");

        System.out.println(obj);
    }
}

运行结果

4、获取类的方法

获取自己的以及父类的所有的公共方法
import java.lang.reflect.Method;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //获取所有的公共方法
        Method[] methods = c.getMethods();
        //输出方法
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

结果展示

获取所有自己的方法
import java.lang.reflect.Method;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //获取自己所有的方法
        Method[] methods = c.getDeclaredMethods();
        //输出方法
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

结果展示

调用对象的公共无参方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //创建类对象
        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        //获取无参公共的方法
        //第一个参数为方法名,第二个参数为方法参数的class类型
        Method method = c.getMethod("settingTest");
        //调用目标对象方法
        //第一个参数为 对象; 第二个参数为具体参数值
        method.invoke(obj);
    }
}

效果展示

调用对象的私有无参方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //创建类对象
        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        //获取无参私有的方法
        //第一个参数为方法名,第二个参数为方法参数的class类型
        Method method = c.getDeclaredMethod("myTest");
        //创造临时权限
        method.setAccessible(true);
        //调用目标对象方法
        //第一个参数为 对象; 第二个参数为具体参数值
        method.invoke(obj);
    }
}

效果展示

调用有参有返回值的方法
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;

public class TestOne {

    public static void main(String[] args) throws Exception {
        //获取字节码文件对象
        Class c = Class.forName("test.People");
        //创建类对象
        Constructor constructor = c.getConstructor();
        Object obj = constructor.newInstance();
        //获取有参带返回值公共方法
        //第一个参数为方法名,第二个参数为方法参数的class类型
        Method method = c.getMethod("settingTest", String.class);
        //调用目标对象方法 并获取返回值
        //第一个参数为 对象; 第二个参数为具体参数值
        Object objString = method.invoke(obj,"私有方法被调用");
        //打印返回值
        System.out.println(objString);
    }
}

效果展示

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值