类型信息(RTTI和反射)

前言

Java程序在运行时的类型信息可以使得我们在程序运行时发现和使用类型信息。
Java程序有两种方式让我们在运行时识别对象和类的信息:
- “传统的”RTTI
- 反射机制
RTTI:个人理解,一种思想,让我们的程序在运行时能够识别出具体的对象来,与多态和继承相辅相成,就比如向上转型中,运用的是多态,但是程序在运行时要判断究竟是用哪个具体类型的方法,就靠RTTI来实现,里面又涉及到方法的后期绑定。
反射与RTTI想要做的事是一样的,反射是后面出现的,一个是年轻版一个是老年版。

RTTI的形式

  • 传统的类型转换(Cast):(Shape)Circle,这个例子中平时我们不需要写(Shape),因为多态已经帮我们做了,反射机制内部做的
  • 代表对象的类型的Class对象:Class classType = Class.forName(“className”);Object o = classType.newInstance();【这个newInstance会抛出两种异常,IllegalAccessException和InstantiationException】
  • 关键字A instanceof B( A是B这个类吗?或者A是B的派生类吗?)

反射

RTTI要想知道明确的对象类型,它有一个限制,就是这个类型必须在编译时期就已经知道了。粗糙理解:你要在用之前这个类的类型信息就给你准备好了。如果是在运行过程中出现了一个不是在编译时期就明确的类,那么这个时候就要靠反射来获取这个类的具体类型信息了。比如远程调用以及“基于构建的编程”(集成开发环境IDE)。
当通过反射与一个未知类型的对象打交道的时候,JVM只是简单的检查这个对象,看它属于哪个特定的类。而真正在用它的时候,就必须先加载那个类的Class对象。因此,那些类的.class文件对于JVM来说是必须要获取的:要么在本地上,要么通过网络。
RTTI和反射的真正区别:RTTI是在编译时打开和检查.class文件,而反射的.class文件在编译时是不可获取的,是在运行时打开和检查.class文件。
简单使用:Class类和java.lang.reflect类库对反射提供支持,包括了Field、Method、Constructor类(每个类都实现了Member接口)。Class的getMethod()和getConstructors()方法获得Method和Constructor对象数组,可以用Constructor创建新的对象,然后调用get\set读取和修改与之对应的Field对象关联的字段,用invoke()方法调用与Method对象关联的方法。
反射的强大之处:对于具有特殊访问权限的方法或者域(非 public)、正常情况下我们访问不到的,都可以使用反射来实现,比如private 方法我们可以使用反射。对Method对象的setAccessible(true)进行修改就可以访问了,相似的还有匿名内部类、私有内部类这些、包访问权限在包外用反射去访问等,这样设计就相当于java给程序开发人员留了一条后路,一方面指定一些东西的权限,另一方面又可以用反射区解决一些特定的问题。

动态代理

代理:将要做的事情交给代理的对象,代理对象作为客户端与实际对象的中间人提供实际的操作。
最简单的代理示例:

interface Interface(){
    void doSomething();
    void doSomethingElse();
}

class RealObject implements Interface(){
    public void doSomething(){
        print("doSothing"); 
    }
    public void doSomethingElse(){
        print("doSomethingElse");
    }
}

class SimpleProxy implements Interface{
    private Interface proxied;
    public SimpleProxy(Interface proxied){
        this.proxied = proxied; 
    }
    public void doSomething(){
        proxied.doSomething();//将要做的事情交给代理对象    
    }
    public void doSomethingElse(){
        proxied.doSomethingElse();  
    }
}

public class SimpleProxyDemo(){ 
    public static consumer(Interface iface){
        iface.doSomething();
        iface.doSomethingElse();
    }
    public static void main(String[] args){
        comsumer(new RealObject());
        comsumer(new SimpleProxy(new RealObject));  
    }
}

动态代理:动态地创建代理并动态地处理对所代理的方法的调用,在动态代理上所做的所有调用都会被重定向到单一的调用处理器(一个实现了InvocationHandler)上。

class DynamicProxyHandler implements InvocationHandler{

        private  Object proxied;

        public DynamicProxyHandler(Object proxy) {
            this.proxy = proxy;
        }

        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(proxied, args);//这里是对代理方法所做的处理都在这里,我就直接调用代理对象的相应方法
        }
    }
    //静态方法Proxy.newProxyInstance创建出动态代理对象,需要一个类加载器,想要代理实现的接口列表(就是接口),和调用处理器
    public static void main(String[] args) {

        Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(),
                new Class[]{Interface.class},
                new DynamicProxyHandler(new RealObject()));
        consumer(proxy);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值