Java基础 - 反射简介

Java基础 - 反射简介

反射这个东西其实很常用,但是我们不知道用了这个。就好像我们对于华为,很多人除了手机完全感觉不到我们用了华为的东西,但是只要我们使用网络,有很多华为的东西。只是不是我们直接接触使用的。反射也是,我们很少写反射的代码,但是在Spring里面,注解,以及其他通过定义配置文件就能够达到目的的操作。其实都是利用的反射机制。只是反射代码是人家写的,我们用就好了。

反射

1. 什么是反射

能够分析类能力的程序称为反射
反射能够用来干什么: 下面是Java核心技术里面介绍的几个功能(应该说:运用Java的反射机制,什么Java操作都能干)

  • 在运行时分析类的能力
  • 在运行时查看对象
  • 实现通用的数组操作代码
  • 利用Method对象,这个对象很像C++中的函数指针

反射机制功能其强大,但是使用人员是工具的构造者,我们普通开发人员很少写反射代码(正常玩游戏不好吗?非要开挂)

为什么反射那么强大:因为Java程序运行时,系统为所有对象维护运行时的信息(保存这个信息的类就是Class),这个信息就相当于该类的所有信息。相当于Java程序要运行,会告知虚拟机自身的一切信息。而反射就相当于和虚拟机的代理人,能够获取到类告知虚拟机的信息

我们为什么要学习反射?:即使不学习反射,也不影响做Java开发。但是很多技术可能你知道这样用,但是不知道为什么是这样。例如 Spring的AOP的实现原理(面试的高频题),AOP的核心是动态代理。动态代理有种是通过反射实现; 还有注解,也是通过反射实现的。 但是这不代表我们需要把反射学的很精通,我觉得知道,或者说了解反射就好了。毕竟我们实际上直接使用反射的情况很少

2. 反射相关知识

反射能够获取一个类的所有信息。
类包含什么,一般类包含3种信息
构造器,域(字段,但是Java编程思想一直称之为域),方法
Java的反射包在java.lang.reflect。主要用的有Field(域),Method(方法),和Constructor(构造器)
其中Class在java.lang下

2.1 Class类

Java运行时,虚拟机会保存运行的类的所有信息,保存在Class中
可以通过Object类中的getClass方法获取Class类型的实例Class cl = object.getClass()。也可以通过Class.forName(“类名字”) 名字得是全限定名获取class对象Class cl = Class.forName("java.util.Random")

Class类常用方法:
public T newInstance() 返回该类对象的实例;
getXXX系列方法

  • public Field getField(String name) 返回一个Field对象
  • public Method getMethod(String name, Class<?>… parameterTypes) 返回Method对象
  • public Constructor getConstructor(Class<?>… parameterTypes) 返回构造器对象
  • 其他很多方法

2.2 Field类

描述类中域的类,能够去到域的所有信息private static ReflectionFactory reflectionFactory,例如这个,能获取该行所有的信息

常用方法,主要是用getXX系列方法
field.getName()获取该域的名字
field.getGenericType()获取该域的类型
field.getModifiers()获取该域的访问修饰符

2.3 Method类

描述类中的方法的类,能够获取方法的所有信息

常用方法,主要是getX系列方法
method.getModifiers() 获取该方法的访问修饰符
method.getReturnType() 获取返回类型
method.getName()获取方法名
method.getParameterTypes()获取方法的参数类型,返回一个数字

2.4 Constructor类

描述类中构造器的的类,可以获取构造器中所有的信息

常用方法
public String getName()获取名字
public int getModifiers()获取访问修饰符
public Class<?>[] getParameterTypes() 获取参数类型

3. 应用示例

应用示例写了Class,field,method的示范,Constructor就没写了,都一样的,而且那些API和我也不记得,写的之后临时看源码结构就好了
IDEA快捷键(alt+7),可以看代码的Structure,很方便看到类的各个方法以及返回值

package com.java.basic.reflection;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/**
 * @author dengtiantian
 */
public class ReflectionTest {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, InstantiationException, NoSuchMethodException {
        Demo demo = new Demo("五更依旧朝花落","18871710000");

        //通过类名获取该类的Class对象
        Class cl = Class.forName("com.java.basic.reflection.Demo");
        System.out.println("通过类名获取class对象");
        System.out.println(cl.toString()+ "\n"+cl.toGenericString());
        //通过该类的实例过去该类的Class对象
        cl = demo.getClass();
        System.out.println("通过对象实例获取Class对象");
        System.out.println(cl.toString()+ "\n"+cl.toGenericString());
        System.out.println(demo.toString());

        //通过cl对象动态的创建一个对象,但是
        System.out.println(cl.newInstance());

        Field field = cl.getField("name");

        //获取Demo类name域的名字,类型,访问修饰符
        System.out.println("域名字:"+field.getName()+"域类型"+field.getGenericType().getTypeName()+"访问修饰符"+ Modifier.toString(field.getModifiers()));
        field = cl.getDeclaredField("id");
        //获取Demo类id域的名字,类型,访问修饰符
        System.out.println("域名字:"+field.getName()+"域类型"+field.getGenericType().getTypeName()+"访问修饰符"+ Modifier.toString(field.getModifiers()));

        //获取Demo类setName方法的
        Method method = cl.getMethod("setName", String.class);
        System.out.println("访问修饰符:"+Modifier.toString(method.getModifiers())+"返回类型"+method.getReturnType()+"方法名:"+method.getName()+"输入参数类型:"+ Arrays.toString(method.getParameterTypes()));


    }
}

class Demo{
    private int id;
    public String name;
    private String mobileNum;

    public Demo() {
    }

    public Demo(String name, String mobileNum) {
        this.name = name;
        this.mobileNum = mobileNum;
    }

    public String getName() {
        return name;
    }

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

    public String getMobileNum() {
        return mobileNum;
    }

    public void setMobileNum(String mobileNum) {
        this.mobileNum = mobileNum;
    }

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

4. 小结

反射其实不算难,知道反射能做什么就可以了
将 Class,Field,Method,Constructor这四个类的源码看下就差不多了(或者看对应的API文档)

总目录:Java进阶之路-目录

                昔别君未婚,儿女忽成行
                《赠卫八处士》杜甫
                博主:五更依旧朝花落
                首次发布时间:2020年4月17日17:02:21
                末次更新时间:
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值