反射的初步理解

初始反射

反射是指在Java运行状态中

  1. 给定一个类对象(Class对象),通过反射获取这个类对象(Class对象)的所有成员结构;
  2. 给定一个具体的对象,能够动态地调用它的方法及对任意属性值进行获取和赋值
    这种动态获取类的内容、创建对象、以及动态调用对象方法及操作属性的机制,就叫做Java的反射机制
    https://docs.oracle.com/javase/8/docs/api/

优缺点:

  1. 增加程序的灵活性,避免将固有的逻辑程序写死到代码里
  2. 代码简洁,可读性强,可提高代码的复用率
    缺点
  3. 相较直接调用在创建对象比较多的情景下反射性能下降
  4. 内部暴露和安全隐患(破坏单例)

反射性能慢原因

  1. 寻找类Class字节码的过程,比如通过ClassName找到对应的字节码Class,然后进行加载、解析,也会比较慢,而new的方式则无需寻找,因为在Linking的解析阶段已经将符号引用转为了直接引用
  2. 安全管理机制的权限验证等等
  3. 若需要调用native方法调用时JNI接口的使用
  4. 入参校验

jdk底层源码查看:http://hg.openjdk.java.net/ 选择具体版本查看jdk和hotspot源码

反射的基本操作

Class对象的组成
Class对象的组成

获取Class对象的四种方式

  1. 通过ClassLoader对象的loadClass()方法
  2. 类名.class
  3. Class.forName() // 会初始化
  4. object.getClass() // 会初始化

在这里插入图片描述

Person类:

import java.lang.reflect.Method;

public class Person {

    static {
        System.out.println("初始化...");
    }

    private String name;

    public String getName() {
        return name;
    }

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

    public void study() {
        System.out.println("good good study day day up。。。");
    }

    public static void main(String[] args) throws Exception {
        // 获取Class对象
        Class<Person> clazz = Person.class;
        // 获得类的结构
        System.out.println(clazz.getSuperclass());
        System.out.println(clazz.getClassLoader());
        System.out.println(clazz.getPackage());
        System.out.println(clazz.getName());

        // 动态创建对象
        Person person = clazz.newInstance();

        // 调用方法
        Method studyMethod = clazz.getDeclaredMethod("study");
        studyMethod.invoke(person);

    }
}
public class CoreMain {

    public static void main(String[] args) throws Exception {
        // 1、类名.class方式,该方式不会对类进行初始化操作
        Class<Person> clazz01 = Person.class;
        System.out.println(clazz01);
        // 2、Class.forName,该方式会进行类的初始化操作,例如MySQL驱动加载
        Class<?> clazz02 = Class.forName("com.jw.javacore.reflection.pojo.Person");
        System.out.println(clazz02);
        // 3、对象.getClass(),会初始化
        Class<? extends Person> clazz03 = new Person().getClass();
        System.out.println(clazz03);
        // 4、通过类加载器.loadClass(),不会初始化
        Class<?> clazz04 = CoreMain.class.getClassLoader().loadClass("com.jw.javacore.reflection.pojo.Person");
        System.out.println(clazz04);
    }
}

基本信息操作
int modifier = clazz.getModifiers(); // 获取类修饰符
Package aPackage = clazz.getPackage(); // 获取类包名
String fullClassName = clazz.getName(); // 获取类的全路径名称
String simpleName = clazz.getSimpleName(); // 获取类的简单名称
ClassLoader classLoader = clazz.getClassLoader(); // 获取类加载器
Class[] interfaces = clazz.getInterfaces(); // 获取类实现的接口列表
Class superclass = clazz.getSuperclass(); // 获取类的父类
Annotation[] annotations = clazz.getAnnotations(); // 获取类的注解信息

    @Test
    public void testBasicOperate() throws Exception {
        Class<Person> clazz01 = Person.class;
        System.out.println(clazz01);
        // 通过Clazz获取基本信息;属性信息;方法信息;注解信息
        System.out.println("--------------");
        int modifiers = clazz01.getModifiers();// 获取的是类的修饰符
        System.out.println(modifiers);
        System.out.println(clazz01.getPackage());
        System.out.println(clazz01.getName());
        System.out.println(clazz01.getSimpleName());
        System.out.println(clazz01.getClassLoader());
        System.out.println(clazz01.getInterfaces());
        System.out.println(clazz01.getSuperclass());
        System.out.println(clazz01.getAnnotations());
    }

类的属性操作示例

    @Test
    public void testFields() throws Exception {
        Class<User> clazz = User.class;
        User user = clazz.newInstance();// 反射调用的无参的构造方法

        System.out.println("--------------");
        Field[] fields = clazz.getFields();// 所有public字段、包括继承来的
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        System.out.println("--------------");
        Field[] declaredFields = clazz.getDeclaredFields();// 获取当前类中定义的字段
        for (Field field : declaredFields) {
            System.out.println(field.getName());
        }

        System.out.println("--------------");
        Field addressField = clazz.getDeclaredField("address");// 获取指定名称的类中定义的字段
        int modifiers = addressField.getModifiers();// 获取字段的修饰符
        addressField.setAccessible(true); // 设置字段的强制访问
        addressField.set(user, "极北之地");// 修改字段你的值
        System.out.println(user.getAddress());

        Field nationalityField = clazz.getDeclaredField("nationality");
        nationalityField.set(null, "光明帝国");// 静态字段赋值
        System.out.println(user.nationality);
    }

类的方法操作

    @Test
    public void testMethods() throws Exception {
        Class<User> clazz = User.class;
        User user = clazz.newInstance();// 反射调用的无参的构造方法

        System.out.println("--------------");
        Method[] methods = clazz.getMethods();// 获取所有的public方法、包括继承来的
        for (Method method : methods) {
            System.out.println(method);
        }

        System.out.println("--------------");
        Method[] declaredMethods = clazz.getDeclaredMethods();// 获取类中定义的方法
        for (Method method : declaredMethods) {
            System.out.println(method);
        }

        System.out.println("--------------");
        Method play = clazz.getMethod("play", String.class);// 获取类中指定名称和参数的公有方法
        int modifiers = play.getModifiers();// 获取方法的修饰符
        Object result = play.invoke(user, "紫川秀");// 指定对象进行成员方法的调用
        play.setAccessible(true);// 指定方法的强制执行
        Method playNoParam = clazz.getMethod("play");// 获取类中指定名称的公有方法
        playNoParam.invoke(user);
        playNoParam.invoke(null);// 静态方法调用
    }

类的构造器操作
Constructor[] cons = clazz.getConstructors(); //获取类中所有的公有构造器
Constructor[] cons1 = clazz.getDeclaredConstructors(); //获取类中所有的构造器
Constructor conNoParam= clazz.getDeclaredConstructor(); //获取类中无参的构造器
Constructor con= clazz.getDeclaredConstructor(String.class,String.class); //获取类中有参构造
int modifers = con.getModifiers(); //获取构造器的修饰符
conNoParam.newInstance(); //构造器实例对象
con.setAccessible(true); //指定方法的强制访问
con.newInstance(“abc”,“bbb”); //有参构造调用
Person.class.newInstance(); //class直接调用默认无参构造

    @Test
    public void testConstructors() throws Exception {
        Class<User> clazz = User.class;

        Constructor<User> declaredConstructor = clazz.getDeclaredConstructor(String.class, String.class);
        declaredConstructor.setAccessible(true);
        User user1 = declaredConstructor.newInstance("idCard", "address");
        User user2 = clazz.newInstance(); // 通过无参的构造函数反射出来的,无参的构造函数需要是public
        System.out.println(user1);
        System.out.println(user2);
    }

构造器操作会对单例模式造成破坏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值