Java 反射机制

视频连接

1、概念

反射机制可以在程序运行期间获取类的信息(成员变量、构造器、成员方法等),并能操作对象的属性及方法。

类加载完成之后,在堆中产生了一个Class类型的对象(一个类中只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构,这个对象就像一面镜子,透过这个镜子看到类的结构,所以形象的称之为:反射

2、 Class类

  • Class也是类,因此继承Object类
  • Class类对象不是new出来的,而是系统创建的
  • 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  • 每个类的实例都会记得自己是由那个Class实例所生成
  • 通过Class可以完整的得到一个类的完整结构,通过一系列API
  • Class对象是存放在堆中
  • 类的字节码二进制数据,是放在方法区的(元数据),包括方法代码,变量名,方法名,访问权限等

2.1、Class类的常用方法

方法名功能说明
Class forName(String name) 返回指定类名name 的 Class对象
Object newInstance()调用缺省构造函数,返回该Class对象的一个实例
getName()返回此Class对象所表示的实体(类、接口、基本类型等)名称
Class[] getInterfaces()获取当前Class对象的接口
ClassLoader getClassLoader()返回该类的类加载器
Class getSuperClass()返回表示此Class所表示的实体类的超类的Class
Constructor[] getConstructors()返回一个包含某些Constructor对象的数组
Field[] getDeclaredFields()返回Field对象的一个数组
Method getMethod(String name,Class ... paramTypes)返回一个Method对象,此对象的形参类型为paramType

2.2、获取Class的几种方式

1、已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法Class.forName()来获取。多用于配置文件,读取类全路径,加载类

2、若已知具体的类,通过类的class获取,该方式最为安全可靠,程序性能最高。

例:Class clazz = Cat.class; 多用于参数传递,比如通过反射得到对应构造器对象

3、已知某个类的实例,调用该实例的getClass()方法获取Class对象。

例:Class clazz = 对象.getClass(); 多用于通过创建好的对象,获取Class对象

 4、通过类加载器加载Class对象

ClassLoader cl = 对象.getClass().getClassLoader();

例:Class clazz = cl.loadClass("类的全类名")

5、基本数据类型获取Class对象

例:Class clazz = 基本数据类型.class

6、基本数据类型对应的包装类,可以通过.TYPE得到Class对象

例:Class clazz = 包装类.TYPE

2.3、获取Class类的结构信息

方法名方法说明
getName获取全类名
getSimpleName获取简单类名
getFields获取所有public修饰的属性,包含本类及父类的
getDeclaredFields获取本类中所有属性
getMethods获取所有public修饰的方法,包含本类及父类的
getDeclaredMethods获取本类中所有方法
getConstructors获取本类所有public修饰的构造器
getDeclaredConstructors获取本类中所有的构造器
getPackage以Package形式返回包信息
getSuperClass以Class形式返回父类信息
getInterface以Class[] 形式返回接口信息
getAnnotations以Annotation[] 形式返回注解信息

3、实例

3.1、反射爆破创建实例对象

package com.tk.reflection;

import java.lang.reflect.Constructor;

/**
 * 通过反射创建对象
 *
 * @author taoke
 * @date 2022/6/1
 */
public class CreateInstance {

    public static void main(String[] args) throws Exception {
        //1、获取Cat类的Class对象
        Class<?> clazz = Class.forName("com.tk.reflection.Cat");
        //2、通过public的无参构造器创建实例
        Object o = clazz.newInstance();
        System.out.println(o);
        //3.1 得到对应的构造器
        Constructor<?> constructor = clazz.getConstructor(String.class);
        //3.2 创建实例,并传入参数
        Object instance = constructor.newInstance("taoke");
        System.out.println("instance=" + instance);
        //4.1、通过非public的有参构造创建实例
        //爆破(暴力破解),使用反射可以访问private构造器/方法/属性,反射面前,都是纸老虎
        Constructor<?> constructor1 = clazz.getDeclaredConstructor(String.class, int.class);
        constructor1.setAccessible(true);
        //4.2、创建实例
        Object instance1 = constructor1.newInstance("taoke", 18);
        System.out.println("instance1=" + instance1);
    }


}

class Cat {
    public String name;

    private int age;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    private Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void hello() {
        System.out.println("喵喵喵:" + name);
    }

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

3.2、反射爆破操作属性

package com.tk.reflection;

import java.lang.reflect.Field;

/**
 * 通过反射创建对象
 *
 * @author taoke
 * @date 2022/6/1
 */
public class CreateInstance {

    public static void main(String[] args) throws Exception {
        //1、获取Cat类的Class对象
        Class<?> clazz = Class.forName("com.tk.reflection.Cat");
        //2、通过public的无参构造器创建实例
        Object o = clazz.newInstance();
        System.out.println(o.getClass());
        //使用反射获取name属性
        Field nameField = clazz.getField("name");
        //通过反射操作属性
        nameField.set(o, "zhangsan");
        System.out.println(o);
        //使用反射操作age属性
        Field ageField = clazz.getDeclaredField("age");
        ageField.setAccessible(true);
        ageField.set(o, 20);
        System.out.println(o);
    }


}

class Cat {
    public String name;

    private int age;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    private Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void hello() {
        System.out.println("喵喵喵:" + name);
    }

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

3.3、反射爆破操作方法

package com.tk.reflection;

import java.lang.reflect.Method;

/**
 * 通过反射创建对象
 *
 * @author taoke
 * @date 2022/6/1
 */
public class CreateInstance {

    public static void main(String[] args) throws Exception {
        //1、获取Cat类的Class对象
        Class<?> clazz = Class.forName("com.tk.reflection.Cat");
        //2、通过public的无参构造器创建实例
        Object o = clazz.newInstance();
        System.out.println(o.getClass());
        //3、得到hello方法
        Method method = clazz.getMethod("hello", String.class);
        //3.1 调用方法
        method.invoke(o, "taoke");
        //4、得到 hi方法
        Method declaredMethod = clazz.getDeclaredMethod("hi", String.class);
        //4.1、因为 hi() 是私有方法,所以需要爆破
        declaredMethod.setAccessible(true);
        //4.2 调用 hi()
        declaredMethod.invoke(o, "taoke");
    }
}

class Cat {
    public String name;

    private int age;

    public Cat() {
    }

    public Cat(String name) {
        this.name = name;
    }

    private Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void hello(String name) {
        System.out.println("喵喵喵~" + name);
    }

    private void hi(String name) {
        System.out.println("hi~" + name);
    }

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值