读书笔记——类型信息

  本片将讨论java是如何让我们在运行时识别对象和类的信息。主要有两种方式:①“传统的”RTTI(Run Time Type Identification)——它假定我们在编译时已经知道了所有的类型②“反射”机制,它允许我们在运行时发现和使用类的信息

1、为什么需要RTTI

2、Class对象

  2.1Class.forName("类名");

    如果这个类没有被加载进来的时候,会先去加载这个类。

  2.2类字面常量——类名.class

    使用.class来创建Class的引用的时候,不会自动初始化该类,相比forName而言更高效。

    static final变量——编译期常量,这中变量是不需要对类进行初始化就可以被读取。这个必须要求是常量,有些虽然是static final变量,但是对其初始化的时候并没有明确赋一个常量,这种变量访问的时候就需要初始化类(例如:static final a=new Random().nextInt(100);这种的就不符合编译期常量的定义)。(详见java编程思想——319页)

    也就是说,对一个static 域不是final的,那么在对其访问的时候就需要先去初始化类。

  2.3泛化的Class引用——提供编译期类型检查

    Class引用总是指向某个Class对象,他可以制造类的实例,并包含可作用于这些实例的所有方法代码。还包含该类的静态成员。因此,Class的引用表示的就是它所指向的对象的确切类型。

    为了在使用泛化的Class引用时放松限制,可以采用通配符。Class<?> class=XXX.class;

    样例代码:Class<?> intClass=int.class;

         intClass=double.class;

    为了将创建的Class引用限定在某种类型,或者该类型的任何子类型,这个时候通过通配符和extends来限定某个范围。

    样例代码:Class<? extends Number> bounded=int.class;

         bounded=double.class;

         bounded=Number.class;

  2.4newInstance()

    这个函数要求你要创建的对象的类必须有一个默认构造器(无参构造器),返回该对象的确切类型。

3、类型转换前先做检查

  向上转型为什么不需要做检查,向下转型就需要做检查?以Shape为例,Shape导出类有Circle、Square和Triangle,由于知道Circle肯定是Shape,所以编译器允许自由的向上转型。向下转型,Shape转换为Circle,你怎么知道这个形状到底是什么具体的形状呢,所以编译器不允许自由向下转换,需要先做一个检查。

4、注册工厂

  使用了注册工厂,相当于导出类统一了一套创建方法,用户只需要去使用就好。

5、反射

  反射提供了一种机制——用来检查可用的方法,并返回方法名。人们想要在运行时获取类的信息的另一个动机是希望提供在网络上跨网络平台上创建和运行对象的能力。这被称为远程方法调用(RMI),它允许java程序将对象分布到多台机器上。

  Class类和java.lang.reflect类库一起对反射的概念进行了支持。

  加入反射的工厂类是不用修改的。

6、动态代理

  代理——设计模式,其目的就是为其他的对象提供了一个代理以控制某个对象的访问。代理类主要负责为委托类预处理消息,过滤并转发消息,以及进行消息被委托类执行后的后续处理。代理类与委托类实现同一个接口,所以在访问者看来并没有太大区别。通过代理类这中间一层,能有效控制对委托类的对象的直接访问,也可以很好的隐藏和保护委托类对象,同时也为实施不同策略预留了空间,从而在设计上获得更大的灵活性。

  java动态代理机制更好地实践了代理模式的设计理念。动态代理可以讲所有调用重定向到调用处理器,因此通常会向调用处理器的构造器传递一个“实际对象”的引用。

  java.lang.reflect.Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

  java.lang.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。 

   代理机制及其特点
    1、首先让我们来了解一下如何使用 Java 动态代理。具体有如下四步骤:
    2、通过实现 InvocationHandler 接口创建自己的调用处理器;
    3、通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
    4、通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
    5、通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

    

原文地址:https://www.cnblogs.com/sylz/p/5903430.html