反射-Reflection

反射

1.获取类对象(三种途径)

  • Hero.class
    
  • Class.forName()
    
  • new Hero().getClass() 
    

注:当前获取类对象会加载类的静态属性(除了

Class c = Hero.class

这种方式)

2.创建一个对象

ReflectionTestClass p = new ReflectionTestClass("男");
Class<? extends ReflectionTestClass> c = p.getClass();//类对象
Constructor<?> constructor = c.getConstructor();//构造器
ReflectionTestClass o = (ReflectionTestClass)constructor.newInstance()//通过构造器进行实例化
o.setAge(12);
System.out.println(o);

3.获取属性(字段)

Class类提供了以下几个方法来获取字段:

  • Field getField(name):根据字段名获取某个public的field(包括父类)
  • Field getDeclaredField(name):根据字段名获取当前类的某个field(不包括父类)
  • Field[] getFields():获取所有public的field(包括父类)
  • Field[] getDeclaredFields():获取当前类的所有field(不包括父类)

getField和getDeclaredField的区别
这两个方法都是用于获取字段
getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。 (: 这里只能获取到private的字段,但并不能访问该private字段的,除非加上setAccessible(true))

ReflectionTestClass p = new ReflectionTestClass("男");
Class<? extends ReflectionTestClass> c = p.getClass();
Field age = c.getDeclaredField("sex");
age.setAccessible(true);//因其属性是private 所以拿到需要加该语句
age.set(p, "女");//修改该字段的
System.out.println(age.get(p));

4.调用方法

Class类提供了以下几个方法来获取Method

  • Method getMethod(name, Class...):获取某个publicMethod(包括父类)
  • Method getDeclaredMethod(name, Class...):获取当前类的某个Method(不包括父类)
  • Method[] getMethods():获取所有publicMethod(包括父类)
  • Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类
ReflectionTestClass p = new ReflectionTestClass("男");
Method m = p.getClass().getMethod("setId", int.class);
m.invoke(p,12);
System.out.println(p.getId()+" ");

5.cron表达式格式:{秒数} {分钟} {小时} {日期} {月份} {星期} {年份(可为空)}

“* ”

“30 * * * * ?” 每半分钟触发任务
“30 10 * * * ?” 每小时的10分30秒触发任务
“30 10 1 * * ?” 每天1点10分30秒触发任务
“30 10 1 20 * ?” 每月20号1点10分30秒触发任务
“30 10 1 20 10 ? *” 每年10月20号1点10分30秒触发任务
“30 10 1 20 10 ? 2011” 2011年10月20号1点10分30秒触发任务
“30 10 1 ? 10 * 2011” 2011年10月每天1点10分30秒触发任务
“30 10 1 ? 10 SUN 2011” 2011年10月每周日1点10分30秒触发任务
“15,30,45 * * * * ?” 每15秒,30秒,45秒时触发任务
“15-45 * * * * ?” 15到45秒内,每秒都触发任务
“15/5 * * * * ?” 每分钟的每15秒开始触发,每隔5秒触发一次
“15-30/5 * * * * ?” 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
“0 0/3 * * * ?” 每小时的第0分0秒开始,每三分钟触发一次
“0 15 10 ? * MON-FRI” 星期一到星期五的10点15分0秒触发任务
“0 15 10 L * ?” 每个月最后一天的10点15分0秒触发任务
“0 15 10 LW * ?” 每个月最后一个工作日的10点15分0秒触发任务
“0 15 10 ? * 5L” 每个月最后一个星期四的10点15分0秒触发任务
“0 15 10 ? * 5#3” 每个月第三周的星期四的10点15分0秒触发任务

6.调用构造方法

通过Class实例获取Constructor的方法如下:

  • getConstructor(Class...):获取某个publicConstructor
  • getDeclaredConstructor(Class...):获取某个Constructor
  • getConstructors():获取所有publicConstructor
  • getDeclaredConstructors():获取所有Constructor

注意Constructor总是当前类定义的构造方法,和父类无关,因此不存在多态的问题。

调用非publicConstructor时,必须首先通过setAccessible(true)设置允许访问。setAccessible(true)可能会失败。

7.动态代理

在运行期动态创建一个interface实例的方法如下:

  1. 定义一个InvocationHandler实例,它负责实现接口的方法调用;

  2. 通过

    Proxy.newProxyInstance()
    

    创建

    interface
    

    实例,它需要3个参数:

    1. 使用的ClassLoader,通常就是接口类的ClassLoader
    2. 需要实现的接口数组,至少需要传入一个接口进去;
    3. 用来处理接口方法调用的InvocationHandler实例。
  3. 将返回的Object强制转型为接口。

    public class Main {
        public static void main(String[] args) {
            InvocationHandler invocationHandler = new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println(method);
                    if (method.getName().equals("morning")){
                        System.out.println("Good morning, " + args[1]);
                    } else if(method.getName().equals("lunch")) {
                        System.out.println("Good afternoon, " + args[0]);
                    }
                    return null;
                }
            };
            Hello o = (Hello)Proxy.newProxyInstance(
                    Hello.class.getClassLoader(), //传入Classloader
                    new Class[]{Hello.class}, //传入要实现的接口
                    invocationHandler); //传入处理调用方法的InvocationHandler
            o.morning("Bob", 12);
            o.lunch(13);
        }
    }
    
    interface Hello {
    
        void morning(String name, int age);
    
        void lunch(int age);
    }
    
上一篇:不同几种剔除(Culling)在渲染流程中的使用总结


下一篇:游戏中遮挡剔除方案总结