反射

本文介绍了Java反射机制的基本概念,包括如何获取Class对象、构造器对象、成员变量对象以及方法对象。通过示例代码展示了使用反射技术动态创建对象、访问私有成员以及调用方法的过程,强调了反射在运行时动态获取类信息和破坏封装性的作用。
摘要由CSDN通过智能技术生成

1、简介

1.1 概念

反射是指对于任何一个Class类,在运行的时候都可以直接得到这个类全部成分。
在运行时,可以直接得到这个类的构造器对象:Constructor。
在运行时,可以直接得到这个类的成员变量对象:Field。
在运行时,可以直接得到这个类的成员方法对象:Method。
这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

1.2 反射的关键

反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分。

HelloWorld.java -> javac -> HelloWorld.class
Class c = HelloWorld.class;

1.3 反射的作用

反射是在运行时获取类的字节码文件对象:然后可以解析类中的全部成分。
反射的核心思想和关键就是:得到编译以后的class文件对象。

2、反射获取类对象

2.1 获取Class类的对象的三种方式

没有junit基础的建议先看一下,链接: https://blog.csdn.net/cndiafcbsfiuv/article/details/128587373?spm=1001.2014.3001.5501
获取class对象
新建一个Student类

package com.cp;
public class Student {
}

新建一个Test类

package com.cp;
public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        //1、Class类中的静态方法:forName(全限定名 包名+类名)
        Class c = Class.forName("com.cp.Student");
        System.out.println(c);

        //2、类名.class
        Class c1 = Student.class;
        System.out.println(c1);

        //3、对象.getClass() 获取对象对应类的class对象
        Student s = new Student();
        Class c2 = s.getClass();
        System.out.println(c2);
    }
}

3、反射获取构造器对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
反射获取构造器对象
新建一个Student后续使用

package com.cp;

public class Student {
    private String name;
    private int age;
    public static String schoolName;
    public static final String COUNTRY = "中国";

    public Student() {
        System.out.println("无参构造器");
    }

    public Student(String name, int age) {
        System.out.println("有参数构造器");
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


3.1 Class类中用于获取构造器的方法

方法说明
Constructor<?>[] getConstructors​()返回所有构造器对象的数组(只能拿public的)
Constructor<?>[] getDeclaredConstructors​()返回所有构造器对象的数组,存在就能拿到
Constructor getConstructor​(Class<?>… parameterTypes)返回单个构造器对象(只能拿public的)
Constructor getDeclaredConstructor​(Class<?>… parameterTypes)返回单个构造器对象,存在就能拿到
package com.cp;
import org.junit.Test;
import java.lang.reflect.Constructor;
public class TestStudent01 {
    @Test
    public void getConstructors(){
        //1、获取类对象
        Class c = Student.class;

        //2、提取类中的全部public构造器对象
        Constructor[] constructors = c.getConstructors();

        //3、遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + constructor.getParameterCount());
        }
    }
    @Test
    public void getDeclaredConstructors(){
        //1、获取类对象
        Class c = Student.class;

        //2、提取类中的全部构造器对象
        Constructor[] constructors = c.getDeclaredConstructors();

        //3、遍历构造器
        for (Constructor constructor : constructors) {
            System.out.println(constructor.getName() + constructor.getParameterCount());
        }
    }

    @Test
    public void getConstructor() throws NoSuchMethodException {
        //1、获取类对象
        Class c = Student.class;

        //2、提取类中的全部public构造器对象
        Constructor constructor = c.getConstructor();

        //3、打印构造器
        System.out.println(constructor.getName() + constructor.getParameterCount());
    }

    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException {
        //1、获取类对象
        Class c = Student.class;

        //2、提取类中的全部public构造器对象
        Constructor constructor = c.getDeclaredConstructor();

        //3、打印构造器
        System.out.println(constructor.getName() + constructor.getParameterCount());

        //2、提取类中的全部public构造器对象
        Constructor constructor1 = c.getDeclaredConstructor(String.class,int.class);

        //3、打印构造器
        System.out.println(constructor1.getName() + constructor1.getParameterCount());
    }
}

3.2 使用反射技术获取构造器对象并使用

方法说明
T newInstance​(Object… initargs)根据指定的构造器创建对象
public void setAccessible(boolean flag)设置为true,表示取消访问检查,进行暴力反射
package com.cp;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestStudent02 {
    @Test
    public void getDeclaredConstructor() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        //1、获取类对象
        Class c = Student.class;

        //2、提取类中的全部public构造器对象
        Constructor constructor = c.getDeclaredConstructor();

        //3、打印构造器
        System.out.println(constructor.getName() + constructor.getParameterCount());
        //暴力反射
        constructor.setAccessible(true);//权限被打开
        //无参构造器为private类型,直接调用会报错,加上上面那一句
        Student s = (Student) constructor.newInstance();
        System.out.println(s);

        //2、提取类中的全部public构造器对象
        Constructor constructor1 = c.getDeclaredConstructor(String.class,int.class);

        //3、打印构造器
        System.out.println(constructor1.getName() + constructor1.getParameterCount());
        constructor1.newInstance("孙悟空",1000);
        System.out.println(constructor1);
    }
}

3.3 使用反射技术获取构造器的作用

1、创建对象
2、如果是非public的构造器,需要打开权限(暴力反射setAccessible(boolean)),然后再创建对象

4、反射获取成员变量对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
反射获取成员变量对象

4.1 Class类中用于获取成员变量的方法

方法说明
Field[] getFields​()返回所有成员变量对象的数组(只能拿public的)
Field[] getDeclaredFields​()返回所有成员变量对象的数组,存在就能拿到
Field getField​(String name)返回单个成员变量对象(只能拿public的)
Field getDeclaredField​(String name)返回单个成员变量对象,存在就能拿到

4.2 使用反射技术获取成员变量对象并使用

方法说明
void set​(Object obj, Object value)赋值
Object get​(Object obj)获取值
package com.cp;

import org.junit.Test;

import java.lang.reflect.Field;

public class FieldDemo01 {
    @Test
    public void getDeclaredFields(){
        //1、定位Class对象
        Class c = Student.class;
        //2、定位全部成员变量
        Field[] fields = c.getDeclaredFields();
        //3、遍历成员变量
        for (Field field : fields) {
            System.out.println(field.getName()+"   "+field.getType());
        }
    }

    @Test
    public void getDeclaredField() throws NoSuchFieldException, IllegalAccessException {
        //1、定位Class对象
        Class c = Student.class;
        //2、定位某个成员变量
        Field field = c.getDeclaredField("name");
        //3、打印成员变量
        System.out.println(field.getName()+"   "+field.getType());

        //4、赋值
        Student s = new Student();
        //暴力打开权限
        field.setAccessible(true);
        field.set(s,"测试");
        System.out.println(s);

        //5、取值
        String name = (String) field.get(s);
        System.out.println(name);
    }
}

4.3 使用反射技术获取成员变量对象的作用

1、在某个对象中取值和赋值。
2、如果某成员变量是非public的,需要打开权限(暴力反射setAccessible(boolean)),然后再取值、赋值

5、反射获取方法对象

反射的第一步是先得到类对象,然后从类对象中获取类的成分对象。
反射获取方法对象

4.1Class类中用于获取成员方法的方法

方法说明
Method[] getMethods​()返回所有成员方法对象的数组(只能拿public的)
Method[] getDeclaredMethods​()返回所有成员方法对象的数组,存在就能拿到
Method getMethod​(String name, Class<?>… parameterTypes)返回单个成员方法对象(只能拿public的)
Method getDeclaredMethod​(String name, Class<?>… parameterTypes)返回单个成员方法对象,存在就能拿到

4.2 使用反射技术获取方法对象并使用

获取成员方法的作用依然是在某个对象中进行执行此方法

方法说明
Object invoke​(Object obj, Object… args)参数一:用obj对象调用该方法,参数二:调用方法的传递的参数(如果没有就不写)返回值:方法的返回值(如果没有就不写)
package com.cp;

public class Dog {
    private Student name;

    public Dog() {
    }

    public Dog(Student name) {
        this.name = name;
    }

    private void run(){
        System.out.println("狗跑");
    }

    private String eat(String name){
        System.out.println("狗吃"+name);
        return "吃的很开心";
    }

    public static void inAddr(){
        System.out.println("静态方法地址");
    }

    private void eat(){
        System.out.println("狗吃");
    }

    public Student getName() {
        return name;
    }

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

package com.cp;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodDemo01 {
    @Test
    public void getDeclaredMethods(){
        //1、获取类对象
        Class c = Dog.class;

        //2、提取全部方法,包括私有的
        Method[] methods = c.getDeclaredMethods();

        //3、遍历全部方法
        for (Method method : methods) {
            System.out.println("方法名    "+method.getName()+" 返回值类型  "+method.getReturnType() +"  参数个数   "+method.getParameterCount());
        }
    }

    @Test
    public void getDeclaredMethod() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1、获取类对象
        Class c = Dog.class;

        //2、提取某个方法,包括私有的
        Method method = c.getDeclaredMethod("eat");
        Method method1 = c.getDeclaredMethod("eat",String.class);

        //3、打印方法信息
        System.out.println("方法名    "+method.getName()+" 返回值类型  "+method.getReturnType() +"  参数个数   "+method.getParameterCount());
        System.out.println("方法名    "+method1.getName()+" 返回值类型  "+method1.getReturnType() +"  参数个数   "+method1.getParameterCount());

        //4、触发方法执行
        Dog d = new Dog();
        //暴力反射,打开权限
        method.setAccessible(true);
        //如果方法没有返回结果,返回为null
        Object result = method.invoke(d);
        System.out.println(result);

        method1.setAccessible(true);
        Object result1 =  method1.invoke(d,"骨头");
        System.out.println(result1);
    }
}

4.3 使用反射技术获取方法对象的作用

1、在某个对象中触发该方法执行。
2、如果某成员方法是非public的,需要打开权限(暴力反射setAccessible(boolean)),然后再触发执行

反射可以破坏封装性,私有的也可以执行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值