• 反射


    1.反射技术应用场景和特点

    反射技术:动态的获取指定类以及动态的调用类中的内容。

    应用场景:现在开发了一个my app的应用程序,想对其中的功能进行扩展,那么怎么能让后期出现的类被写好的应用程序所使用呢?通常的做法是实现相应的接口,实现完接口之后呢?我们需要在my app的源代码中使用接口创造相关对象。然而,app一般不会提供给你源代码,只是提供给你了.class文件,没法new 创建对象,这下怎么办呢?

    2.字节码文件对应的类

    3.获取字节码文件对象 

    package cn.itcast.reflect.demo;
    
    import cn.itcast.reflect.domain.Person;
    
    public class Reflect_GetClassDemo {
    
        public static void main(String[] args) {
            /*
             * 要想获取字节码文件中的成员,要先获取字节码文件对象。 获取字节码文件对象方式: 
             * 1.通过object类中的getClass方法。
             * 虽然通用,但是前提必须要指定类,并对该类进行对象的创建,才可以调用getClass方法。
             *
             * 2.使用的是任意数据类型的静态成员class,所有数据类型都具备的一个属性。
             * 好处:不用new对象,但是,还需要使用具体的类。
             *
             * 3.使用class类中的forName方法,通过给定类名获取对应的字节码文件对象。
             * 这种方式很爽,只要知道类的名字就可以了,获取对应的字节码文件由forName方法自动完成。
             * 这就是反射技术使用的获取字节码文件对象的方式。
             *
             */
            getClass_1();
            getClass_2();
            getClass_3();
    
        }
    
        private static void getClass_3()  {
            // TODO Auto-generated method stub
            String calssName ="cn.itcast.reflect.domain.Person";
            try {
                Class clazz = Class.forName(calssName);
                System.out.println(clazz.getName());
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        private static void getClass_2() {
            // TODO Auto-generated method stub
            Class clazz = Person.class;
            System.out.println(clazz.getName()); // cn.itcast.reflect.domain.Person
        }
    
        private static void getClass_1() {
            // TODO Auto-generated method stub
            Person p1 = new Person();
            Person p2 = new Person();
            Class clazz1 = p1.getClass();
            Class clazz2 = p2.getClass();
            System.out.println(clazz1.getName()); // cn.itcast.reflect.domain.Person
            System.out.println(clazz1 == clazz2); // true
        }
    
    }

    4.动态创建字节码对象所表示的类的对象

    package cn.itcast.reflect.demo;
    
    import cn.itcast.reflect.domain.Person;
    
    public class Reflect_GetClassDemo {
    
        public static void main(String[] args) throws Exception {
    
            getClass_3();
    
        }
    
        private static void getClass_3() throws ClassNotFoundException, InstantiationException, IllegalAccessException   {
            // TODO Auto-generated method stub
            String calssName = "cn.itcast.reflect.domain.Person";
            Class clazz = Class.forName(calssName);
            System.out.println(clazz.getName());
            // 通过newInstance()就可以创建字节码文件所表示的类的实例。
            Object obj = clazz.newInstance();
        }
    
    
    
    }

    5.常见的异常解析

    package cn.itcast.reflect.demo;
    
    public class Reflect_GetClassDemo {
    
        public static void main(String[] args) throws Exception {
            
            getClass_3();
            
        }
    
        private static void getClass_3() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
            // TODO Auto-generated method stub
            String calssName = "cn.itcast.reflect.domain.Person";
            Class clazz = Class.forName(calssName);
    //        System.out.println(clazz.getName());
            // 通过newInstance()就可以创建字节码文件所表示的类的实例。
            // 通常被反射的类都提供空参数的构造函数,如果没有对应的构造函数,会报InstantiationException
            // 如果有提供,但是权限不够,会报IllegalAccessException
            Object obj = clazz.newInstance(); 
        }
    
    }

    6.通过给定的构造函数进行实例化

    package cn.itcast.reflect.domain;
    
    public class Person {
        private String name;
        private int age;
    
        public Person() {
            // TODO Auto-generated constructor stub
            System.out.println("person run");
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
    
    }
    package cn.itcast.reflect.demo;
    
    import java.lang.reflect.Constructor;
    
    public class Reflect_GetConstructor {
        public static void main(String[] args) throws Exception {
            /*
             * 如果要通过指定的构造函数初始化对象怎么办呢?
             * 思路:
             * 1.获取字节码文件对象;
             * 2.在获取给定的构造函数;
             * 3.通过该构造函数初始化对象。
             */
            getConstructorDemo();
        }
    
        public static void getConstructorDemo() throws Exception {
            // TODO Auto-generated method stub
            String className = "cn.itcast.reflect.domain.Person";
            Class clazz = Class.forName(className);
            
            //获取指定的构造器,获取Person类中带参数的Sting,int构造函数
            Constructor cons = clazz.getConstructor(String.class,int.class);
            //有了构造对象后,通过构造器对象来初始化该类对象
            Object obj = cons.newInstance("lisi",21);
            System.out.println(obj);
        }
        
        
    }

    7.获取字段与暴力访问

    package cn.itcast.reflect.demo;
    
    import java.lang.reflect.Field;
    
    public class Reflect_GetField {
        public static void main(String[] args) throws Exception {
            /*
             * 获取字段
             */
            getFieldDemo();
        }
    
        public static void getFieldDemo() throws Exception {
            // TODO Auto-generated method stub
            String className = "cn.itcast.reflect.domain.Person";
            Class clazz = Class.forName(className);
            
            String fieldName = "age"; 
            //获取字段
    //        Field field = clazz.getField(fieldName);//获取的是公有的字段
            Field declaredField = clazz.getDeclaredField(fieldName);
            System.out.println(declaredField);
            
            //对其进行值的设置,必须先有对象
            Object obj = clazz.newInstance();
    //        declaredField.set(obj, 30); //IllegalAccessException,age字段是私有的,不能直接修改
            declaredField.setAccessible(true);
            declaredField.set(obj, 30);
            
            System.out.println(declaredField.get(obj));//获取字段的值
            
        }
    }
    package cn.itcast.reflect.domain;
    
    public class Person {
        public String name;
        private int age;
    
        public Person() {
            // TODO Auto-generated constructor stub
            System.out.println("person run");
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
    
    }

    8.获取方法

    package cn.itcast.reflect.domain;
    
    public class Person {
        public String name;
        private int age;
    
        public Person() {
            // TODO Auto-generated constructor stub
            System.out.println("person run");
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public void show(String name, int age) {
            System.out.println("show run... name =" + name + ",age=" + age);
        }
    
        public static void staticShow() {
            System.out.println("staticShow run...");
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
    
    }
    package cn.itcast.reflect.demo;
    
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    public class Reflect_GetMethodDemo {
        public static void main(String[] args) throws Exception {
            /*
             * 获取方法
             */
            getMethodDemo();
        }
    
        public static void getMethodDemo() throws Exception {
            // TODO Auto-generated method stub
            String className = "cn.itcast.reflect.domain.Person";
            Class clazz = Class.forName(className);
    
            Object obj = clazz.newInstance();
    
            String methodName = "show";
    
            Method method = clazz.getMethod(methodName, String.class, int.class);
            method.invoke(obj, "wangcai", 20); // show run... name =wangcai,age=20
    
            // 获取静态方法
            String methodName2 = "staticShow";
            Method method2 = clazz.getMethod(methodName2, null);
            method2.invoke(null, null); // staticShow run...
    
        }
    }
  • 相关阅读:
    C# linq根据属性分组,并累加计算
    AR模板分组显示(C#打印)
    显示单据信息(类似打印)
    C#同步方法中调用异步方法
    win10 Git安装或者使用出现128问题
    简单的分页查询实现
    数据库批量插入【数据库】
    VideoView
    音乐播放
    画画板案例
  • 原文地址:https://www.cnblogs.com/xinmomoyan/p/13211012.html
Copyright © 2020-2023  润新知