反射介绍及使用

反射的应用

案例

案例 :美团外卖在线支付:微信,支付宝,银行卡等

/**
  * 美团支付公共接口
  */
public interface Meituanwaimai {
    void payOnline();
}
/**
  * 微信支付
  */
public class WechatPay implements Meituanwaimai{
    @Override
    public void payOnline() {
        System.out.println("用微信支付!");
    }
}
/**
  * 支付宝支付
  */
public class ZhifubaoPay implements Meituanwaimai{
    @Override
    public void payOnline() {
        System.out.println("用支付宝支付!");
    }
}

/**
  *某个银行支付
  */
public class BankCardPay implements Meituanwaimai{
    @Override
    public void payOnline() {
        System.out.println("使用招商银行支付!");
    }
}


public class Test {

    public static void main(String[] args) throws Exception {
        //前端传过来的支付方式
        String payType = "微信";
      // 传统实现:
        if ("微信".equals(payType)){  //payType.equals("微信") 避免空指针
            pay(new WechatPay());  //控制台输出  用微信支付!
        }
        if ("支付宝".equals(payType)){
            pay(new ZhifubaoPay()); //控制台输出  用支付宝支付!
        }
        if ("支付宝".equals(payType)){
            pay(new BankCardPay()); //使用招商银行支付!
        }
        //如果要加支付方式,则此处一直要加if 代码,不利于扩展,用反射可以解决该问题

        //反射的代码
        //前端传过来的支付方式,实际上 是微信类的全限定路径
        String paymetch = "com.gy.fx.springtest.reflect.WechatPay";
        //拿到Class类 即WechatPay类的字节码信息
        Class als = Class.forName(paymetch);
        //创建对象: 用Class 初始化对象
        Object obj = als.newInstance();
        //用Class得到指定方法
        Method method = als.getMethod("payOnline");
        //执行该对象的该方法
        method.invoke(obj); //控制台输出  用微信支付!
    }

    private static void pay(Meituanwaimai pay){
        pay.payOnline();
    }
}

反射的定义

JAVA反射机制是在运行状态中,对任意一个类,都能知道这个类的所有属性和方法;对任意一个对象,都能够调用它的任意方法和属性;
这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

使用

准备数据

/**
 * <h5>描述:作为一个父类</h5>
 */
public class Person implements Serializable {

    private int age;

    public String name;

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

    public void sleep(){
        System.out.println("public Person sleep.....");
    }
}
package com.gy.fx.springtest.reflect;

/**
 * <h5>描述:作为子类</h5>
 */
@MyAnnotation(value = "hello")
public class Student extends Person implements MyInterface{

    //属性
    private  int sno; //私有属性
    double height; //默认属性
    protected double weight; //保护属性
    public  double score; //公有属性

    //方法
    public String show(){
        return "Student public show() ";
    }

    public String show(int a, int b){
        return "Student public show(int a, int b) ";
    }

    private  void work(){
        System.out.println("Student private work()");
    }

    void happy(){
        System.out.println("Student default work()");
    }

    protected  int getSno(){
        return sno;
    }

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

    public Student(int sno, double height, double weight) {
        this.sno = sno;
        this.height = height;
        this.weight = weight;
    }

    private Student(int sno) {
        this.sno = sno;
    }

    Student(int sno, double height) {
        this.sno = sno;
        this.height = height;
    }

    @Override
    @MyAnnotation(value = "hi,dowork")
    public void dowork() {
        System.out.println("自定义接口的方法");
    }

    @Override
    public String toString() {
        return "Student{" +
                "sno=" + sno +
                ", height=" + height +
                ", weight=" + weight +
                ", score=" + score +
                '}';
    }
}

四种获取字节码信息的方式 案例:以Person的字节码信息为案例

//方案1:通过getClass() 方法获取  不常用
        Person person = new Person();
        Class als1 = person.getClass();
        System.out.println(als1);  //class com.gy.fx.springtest.reflect.Person
        //方案2: 通过类名.class 方法获取  不常用
        Class als2 = Person.class;
        System.out.println(als2); //class com.gy.fx.springtest.reflect.Person
        //加载器只加载一次,所以同一个类的 class 肯定是同一个
        System.out.println(als1 == als2); //true
        //方案3  通过Class.forName 获取, 常用
        Class als3 = Class.forName("com.gy.fx.springtest.reflect.Person");
        System.out.println(als3); //class com.gy.fx.springtest.reflect.Person
        //方案4 利用类加载器 不常用  (前置知识:.java文件,编译成 .class文件, jvm通过类加载器 加载到内存区域)
        ClassLoader loader = Demo.class.getClassLoader();
        Class als4 = loader.loadClass("com.gy.fx.springtest.reflect.Person");
        System.out.println(als4); //class com.gy.fx.springtest.reflect.Person

获取 Class 类的具体实例

/**
         * Class 类的具体实例:
         * 1.类:外部类,内部类
         * 2.接口
         * 3.注解
         * 4.数组
         * 5.基本数据类型
         * 6.void
         */
        Class c1 = Person.class; //类
        Class c2 = Comparable.class; //接口
        Class c3 = Override.class; //注解
        int[] arr1 = {1, 2, 3}; //数组
        Class c4 = arr1.getClass();
        int[] arr2 = {4, 5};
        Class c5 = arr2.getClass();
        System.out.println(c4 == c5); //结果:ture ,同一个维度,同一个元素类型,得到的字节码就是同一个
        Class c6 = int.class; //基本数据类型
        Class c7 = void.class;  //void

获取构造器和创建对象

//获取字节码信息
        Class cls = Student.class;
        //通过字节码信息可以获取构造器(构造方法) :
        // getConstructors() 只能获取当前运行时被public 修饰的构造器
        Constructor[] constructors = cls.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);  //public com.gy.fx.springtest.reflect.Student()
        }
        // getConstructors() 能获取当前运行时所有的构造器
        Constructor[] constructors2 = cls.getDeclaredConstructors();
        for (Constructor constructor : constructors2) {
            System.out.println(constructor);  //public com.gy.fx.springtest.reflect.Student()   com.gy.fx.springtest.reflect.Student(int,double)  private com.gy.fx.springtest.reflect.Student(int)
        }
        //获取指定的构造器 ,不传参数时,获取的无参构造器 ,不加dec 只能获取pulic 修饰的构造器
        Constructor constructor = cls.getConstructor(int.class, double.class, double.class);
        //加dec 能获取任何修饰符的构造器
        System.out.println(constructor); // public com.gy.fx.springtest.reflect.Student(int,double,double)
        Constructor constructor2 = cls.getDeclaredConstructor(int.class); //private com.gy.fx.springtest.reflect.Student(int)
        System.out.println(constructor2);

        //用构造器创建对象
        Object o = constructor.newInstance(1, 2.2, 3.4);
        System.out.println(0);

获取属性及属性的具体结构

//获取运行时类的字节码信息
        Class clss = Student.class;
        //根据字节码信息获取属性
        // getFields 获取运行时类和父类被public修饰的属性
        Field[] fields = clss.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        // getDeclaredFields 获取运行时类和父类所有属性
        Field[] fields2 = clss.getDeclaredFields();
        for (Field field : fields2) {
            System.out.println(field);
        }
        //获取指定属性
        //getField 获取public修饰的属性
        Field score = clss.getField("score");
        System.out.println(score); //public double com.gy.fx.springtest.reflect.Student.score
        //getDeclaredField 获取任意修饰符修饰的属性
        Field sno = clss.getDeclaredField("sno");
        System.out.println(sno); //private int com.gy.fx.springtest.reflect.Student.sno

        //属性的具体结构
        //属性的修饰符
        String s = Modifier.toString(sno.getModifiers());
        System.out.println(s); //private
        //属性的数据类型
        Class type = sno.getType();
        System.out.println(type); //int
        //属性的名字
        String name = sno.getName();
        System.out.println(name);  //sno

        //给属性赋值:给属性设置值,必须要有对象
        Field score1 = cls.getField("score");
        Object o1 = cls.newInstance(); //调用无参构造函数初始化对象
        score1.set(o1, 98); //给obj 这个对象的 score属性设置具体值 ,这个值是98
        System.out.println(o1); //Student{sno=0, height=0.0, weight=0.0, score=98.0}

获取方法和调用方法

//获取字节码信息
        Class classs = Student.class;
        //获取方法
        // getMethods() 获取 运行时类 中被public 修饰的方法和 父类中被public修饰的的方法
        Method[] methods = classs.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
        // getDeclaredMethods() 获取 运行时类的所有方法和 父类的所有方法
        Method[] methods2 = classs.getDeclaredMethods();
        for (Method method : methods2) {
            System.out.println(method);
        }
        //获取指定方法
        //getMethod()获取public 修饰的方法
        Method show = classs.getMethod("show");
        System.out.println(show); //public java.lang.String com.gy.fx.springtest.reflect.Student.show()
        Method show2 = classs.getMethod("show", int.class, int.class);
        System.out.println(show2); //public java.lang.String com.gy.fx.springtest.reflect.Student.show(int,int)
        //getDeclaredMethod()获取任意修饰符修饰的方法
        Method show3 = classs.getDeclaredMethod("work");
        System.out.println(show3); //private void com.gy.fx.springtest.reflect.Student.work()


        //获取方法的具体结构:@注解,修饰符,返回值类型,方法名,参数列表,抛出的异常,注解 等
        //方法名
        String name1 = show.getName();
        System.out.println(name1);
        //修饰符
        int modifiers = show.getModifiers();
        System.out.println(Modifier.toString(modifiers));
        //返回值类型
        Class returnType = show.getReturnType();
        System.out.println(returnType); //class java.lang.String
        //参数列表
        Class[] parameterTypes = show.getParameterTypes();
        for (Class aClass : parameterTypes) {
            System.out.println(aClass);
        }

        //获取注解 注意 只能获取到声明周期是运行时  @Retention(RetentionPolicy.RUNTIME) 的注解
        Method dowork = classs.getMethod("dowork");
        Annotation[] annotations = dowork.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }

        //调用方法
        Object o2 = classs.newInstance();
        dowork.invoke(o2); //调用o2对象的dowork 方法
        
        show2.invoke(o2,1,2); //调用o2对象的show(int,int) 方法

获取 类的接口,包,注解等

//获取运行时类的接口
        Class clsss = Student.class;
        Class[] interfaces = clsss.getInterfaces();
        for (Class anInterface : interfaces) {
            System.out.println(anInterface); //interface com.gy.fx.springtest.reflect.MyInterface
        }
        //得到父类的接口:1.先获取父类的字节码信息,2.在获取接口
        Class superclass = clsss.getSuperclass();
        Class[] interfaces1 = superclass.getInterfaces();
        for (Class aClass : interfaces1) {
            System.out.println(aClass); //interface java.io.Serializable
        }

        //获取运行时类所在的包
        Package aPackage = clsss.getPackage();
        System.out.println(aPackage); // package com.gy.fx.springtest.reflect
        System.out.println(aPackage.getName()); // com.gy.fx.springtest.reflect

        //获取运行时类的注解
        Annotation[] annotations1 = clsss.getAnnotations();
        for (Annotation annotation : annotations1) {
            System.out.println(annotation); //@com.gy.fx.springtest.reflect.MyAnnotation(value=hello)
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值