反射

一、通过例子引入反射

 /** 反射案例:

     * 实现美团外卖的支付功能:

     * 1.微信,支付宝,各大银行卡 来实现支付

     * 2.顾客选择支付方式!

     *实现步骤:

      * (1).创建美团接口,支付方法

     *  (2).创建实现类 完成方法的重写

     *  (3).创建测试类,完成流程

*/

【接口:】
/**
 * 美团外卖 支付接口!
 *
 */
public interface MTWM {
    void onlinePayment();
}

【实现类:】
/**
 * 微信 实现支付方式
 */
public class WeChat implements MTWM {
    @Override
    public void onlinePayment() {
        System.out.println("正在使用微信  进行支付。。。");
    }
}

public class Ali implements MTWM {

    @Override
    public void onlinePayment() {
        System.out.println("支付宝 正在进行 支付操作。。。。");
    }
}

public class BanCard implements MTWM {
    @Override
    public void onlinePayment() {
        System.out.println("正在使用银行卡  进行支付操作。。。");
    }
}

【测试类】
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
            //提示用户,选择哪种支付方式:
        Scanner input=new Scanner(System.in);
        System.out.println("请选择支付方式:1.微信,2.支付宝,3.银行卡.....");
       /* int i=input.nextInt();
        if(i==1){
            WeChat weChat=new WeChat();
            pay(weChat);
        }else if(i==2){
            Ali ali=new Ali();
            pay(ali);
        }else if(i==3){
            BanCard banCard=new BanCard();
            pay(banCard);
        }*/
         String str=input.next();
         Class c=Class.forName(str);
         Object o=c.newInstance();
         Method method=c.getDeclaredMethod("onlinePayment");
         method.invoke(o);
}

    public static void pay( MTWM mtwm){
        mtwm.onlinePayment();
    }

/*
    public static void pay( WeChat weChat){
        weChat.onlinePayment();
    }
    public static void pay( Ali ali){
        ali.onlinePayment();
    }
    public static void pay( BanCard banCard){
        banCard.onlinePayment();
    }
*/
运行结果如下:

二、简单介绍反射

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

补充:

动态语言vs静态语言

1、动态语言

动态语言是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。

主要动态语言: Object-C、 C#、JavaScript、 PHP、 Python、 Erlang 。

2、静态语言

与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。

Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活! 

三、获得Class对象的四种方式

/**
*第一种:通过对象名.getClass()获得
*/
Student student=new Student();
Class cla=student.getClass();

/**
*第二种:直接Class.forName()获得
*/
Class cla02=Class.forName("com.demo02.Student");

/**
*第三种:通过类名.class获得
*/
Class cla03=Student.class;

/**
*第四种:通过classLoader.loadClass()获得
*/
ClassLoader classLoader= Test.class.getClassLoader();
Class cla04=classLoader.loadClass("com.demo02.Student");

四、获得构造器、创建对象

//获得构造器,并通过构造器创建对象:
public static void getconstructor() throws 
ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
 InvocationTargetException, InstantiationException {
        //1.获得Class 字节码文件对象:
        Class c=Class.forName("com.demo02.Student");

        //2.获得字节码文件里【公有】的构造器:
       Constructor[] constructors= c.getConstructors();
       for(Constructor constructor:constructors){
           System.out.println(constructor);
       }
       System.out.println("==========");

       //2.2获得字节码文件里【所有】的构造器:
       Constructor[] constructors1= c.getDeclaredConstructors();
        for(Constructor constructor:constructors1){
            System.out.println(constructor);
        }

       //2.3 获得字节码文件里【某一个】构造器: 有参构造器
        Constructor constructor= c.getDeclaredConstructor
(String.class,String.class,String.class,double.class);
        Student stu=(Student)constructor.newInstance("3班","java","长春大学",178);
        System.out.println(stu);
        
        //无参构造器
        Constructor constructor01= c.getDeclaredConstructor();
        Student stu02=(Student)constructor01.newInstance();
        System.out.println(stu02);

    }

五、获得属性、对属性进行取值/赋值

public static void getField01() throws NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {

        //1.获得字节码文件对象:
        Class c=Student.class;

        //2.获得属性:
        //Field[] fields=c.getFields(); //获得当前类+父类里所有的public 修饰的属性
        Field[] fields= c.getDeclaredFields();//获得当前类所有的属性
        //c.getField(); //根据参数 属性名--》获得当前类+父类里某一个public 修饰的属性
       // c.getDeclaredField();//根据参数 属性名--》得当前类+父类里某一个属性
        for (Field field :fields){
            System.out.println("属性名:"+field.getName());
            System.out.println("属性类型:"+field.getType());
            System.out.println("属性修饰符:"+field.getModifiers());
        }

        //3.给属性赋值:
        Field field=  c.getField("heigth");
        Student stu=(Student)c.getConstructor().newInstance(); //无参构造
        field.setDouble(stu,176.5);
        System.out.println(stu);
    }

六、获得行为方法并执行方法

 public static void getMethod01() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        //1.获得字节码文件对象:
        Student stu=new Student();
        Class c=stu.getClass();

        //2.获得方法:
        Method[] methods=c.getMethods();//获得当前类+父类中所有public方法;
     /*   for(Method method:methods){
            System.out.println(method);
        }*/

        //2.2
        Method[] methods02=c.getDeclaredMethods(); //获得本类下的所有方法
        for(Method method:methods02){
            System.out.println(method);
        }

        //3.执行方法:
        //调用 protected,有参的
        Method method=c.getDeclaredMethod("method02",String.class,int.class);
        System.out.println(method.invoke(stu,"张三",90));

       //调用public,有参:
        Method method1=c.getMethod("method01",int.class);
        method1.invoke(stu,100);
    }

七、私有资源调用

通过暴力反射,不让检查属性的权限来调用!
 public static void usePrivate() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //1.获得Class字节码文件对象:
        Class c=Test.class.getClassLoader().loadClass("com.demo02.Student");

        //2.获得私有构造器,同时创建对象:
        Constructor constructor= c.getDeclaredConstructor(String.class);
        constructor.setAccessible(true);//暴力反射,不让检查构造器的权限!
        Student stu=(Student)constructor.newInstance("张三");

        //3.获得私有属性,给属性赋值:
        Field field=c.getDeclaredField("stuid");
        field.setAccessible(true);//暴力反射,不让检查属性的权限!
        field.set(stu,"10-02");

        //4.获得私有方法,同时调用:
        Method method=c.getDeclaredMethod("method02",int.class);
        method.setAccessible(true);//暴力反射,不让检查方法的权限!
        method.invoke(stu,99);
        System.out.println(stu);
    }

八、获得接口和父类

public static void getSuper01(){

        Class c=Student.class;
        Class superClass=c.getSuperclass();  //获得父类

        Field[] fields=superClass.getDeclaredFields(); //获得父类所有方法
        for(Field field:fields){
            System.out.println(field);
        }
    }

九、泛型集合

 public static void main(String[] args) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, NoSuchFieldException {

        ArrayList<Integer> list=new ArrayList<>();
        list.add(90);  //泛型只存在于编译期

        //1.获得ArrayList的字节码文件对象:
        Class c=Class.forName("java.util.ArrayList");

        //2.调用方法:
        Method method= c.getMethod("add",Object.class);
        System.out.println(method);
        method.invoke(list,"zhangsan");

        System.out.println(list.size());
    }

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值