zoukankan      html  css  js  c++  java
  • JAVA编程思想——类型信息(反射)

    一、反射与RTTI

    RTTI:这个类型必须在编译的时候已知或者存在,如果不知道对象的确切类型,RTTI可以告诉你。

    反射(个人认为就是能够利用Class获取或者调用.class这个文件中的数据):当我们从程序外(网络,磁盘中)在程序运行的时候获取这些数据,发现这些数据是个类,并且不知道该类的类型,那么我们怎么使用这些数据呢。

    所以说根本区别是:RTTI在编译的时候会检查和打开.class文件,但是在反射中.class文件是不可获取的,所以在运行时打开和检查.class文件

    二、使用

    利用反射获取类的方法和构造方法

    ublic class UseReflection {
        public static void main(String[]args){
            try {
                Class c = Class.forName("String");
                Method[]methods = c.getMethods();//获取c这个对象的所有方法
                Constructor[]constructors = c.getConstructors();//获取c这个对象的所有构造方法
                for (Method method:methods){
                    method.toString();
                    constructors.toString();
                }
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
    }
    View UseReflection

    三、动态代理

    ①、代理

    作用:将额外的操作从“实际”对象中分离到不同的地方。(特别是当有时候准备使用这个功能,有时候又不需要使用这个功能的时候,这就很容易修改)。

    (感觉就是扩展了这个方法,但是又不是直接在方法内增加,并且还能够选择用或者不用)

    步骤:1、将需要的操作封装为一个接口 2、主类继承这个接口,然后实现 3、创建代理继承接口,然后获取主类,在实现方法的时候,调用新方法然后再调用主类的同样的方法。

    public interface Proxy {
        void doSomething();
        void somethingElse(String make);
    }
    代理接口
    //主类继承了代理类,并重写了该方法
    public class Child implements Proxy{
    
        @Override
        public void doSomething() {
            // TODO Auto-generated method stub
            System.out.println("Play");
        }
    
        @Override
        public void somethingElse(String make) {
            // TODO Auto-generated method stub
            System.out.println("eat fruit");
        }
    
    }
    主类
    //代理类,继承了代理接口,并获取主类对象向上转型为代理,然后在相应方法内,重新调用
    public class SimpeProxy implements Proxy{
        private Proxy mProxy;
        
        public SimpeProxy(Proxy proxy){
            mProxy = proxy;
        }
        
        @Override
        public void doSomething() {
            // TODO Auto-generated method stub
            System.out.println("Footboll");
            //调用主类的该方法
            mProxy.doSomething();
        }
    
        @Override
        public void somethingElse(String make) {
            // TODO Auto-generated method stub
            System.out.println("Footboll"+make);
            mProxy.somethingElse(make);
        }
        
    }
    代理类
    public class AchieveProxy {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            complete(new Child());//未使用代理
            complete(new SimpeProxy(new Child()));//使用代理
        }
    
        public static void complete(Proxy proxy){
            proxy.doSomething();
            proxy.somethingElse("make cake");
        }
    }
    实现逻辑类

    ②、动态代理

    使用:1、用到的类:InvocationHandler接口,和Proxy类

    步骤:1、同样将需要的操作封装成一个接口 2、创建相关类并继承接口   3、创建代理类,该类继承InvocationHandler接口,实现invoke()方法,该方法实现代理的逻辑。

    4、在主线程中调用代理

    示例:

    代理接口和主类不变就不写了。

    //继承接口
    public class DynamicProxy implements InvocationHandler {
        private Object mChild;
        public DanamicProxy(Object child){
            mChild = child;
        }
    //实现接口的方法。
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                throws Throwable {
            // TODO Auto-generated method stub
            
            System.out.println("我是代理,大家好"+"proxy   "+proxy.getClass().getSimpleName());
                   //绑定该方法,参数1、是被被代理对象  参数2、是传送到该方法的值
            return method.invoke(mChild, args);
        }
    }
    /*
    *方法的使用原理:参数1、当前的代理对象   参数2、正在被使用的方法  参数3、对于该方法传入的参数。     
    *
    */
    DynaicProxy
    //创建被代理对象        
    Child child = new Child();
    //创建代理对象
    DanamicProxy dana = new DanamicProxy(child);
    //连接代理与被代理对象    参数1、获取类加载器   参数2、获取代理的接口  参数3、获取代理对象
    Proxy proxy = (Proxy)java.lang.reflect.Proxy.newProxyInstance(child.getClass().getClassLoader(), new Class[]{Proxy.class}, dana);
    //调用代理对象的方法
    complete(proxy);
    
    public static void complete(Proxy proxy){
        proxy.doSomething();
        proxy.somethingElse("make cake");
    }
    实现逻辑

    原理:Proxy类通过反射获取接口的方法,在继承InvcationHandler的类中,当代理调用接口的方法的时候,就会触发invoke()方法,并将用到的方法和参数传入,然后再用用到的方法调用invoke()调用被代理类的相应方法。

    动态代理的优点:①、只需要在invoke()中实现逻辑就可以了,不用因为有多个方法需要代理,就需要重写一堆方法。  ②、代理可以被多个类使用,而不是继承特定接口的类。

    最近用到的Retrofit应该就是用到了动态代理。

    RTTI的新发现:

    Child child = new Child();
    Proxy proxy = (Proxy)child;
    System.out.println(proxy.getClass().getName());
    //答案居然是Child。 说明反射是根据指针来的,向上转型无法改变其name
    View Code
  • 相关阅读:
    Linux操作系统(二)
    匿名函数和内置函数
    BeautifulSoup
    Robots协议
    列表和生成器表达式
    迭代器
    排序总结
    图论专题笔记
    Trie树的二三事QWQ
    二分答案经典入门题:)
  • 原文地址:https://www.cnblogs.com/rookiechen/p/5528356.html
Copyright © 2011-2022 走看看