一、Class对象

Class对象详解

二、类型转换前先做检查

1.instanceof

  A instanceof B
  instanceof用于比较对象A是不是类型B的实例。但是B只能是具体的命名类型(如Integer之类),不能是Class对象。当程序中出现大量instanceof时,说明你的设计可能存在瑕疵,因为大量的instanceof可能能够用以下的方法解决。

//例子
if(A instanceof Integer)
    语句1;
if(A instanceof Double)
    语句2;
...
/*错误,比较类型不能是Class对象。
Class type = ...
if(A instanceof type)
    语句;
*/

2.动态的instanceof

  A.isInstance(B)
  Class.isInstance方法提供了一种动态地测试对象的途径。此时A是Class对象,B是对象。这样就解决了需要大量使用instanceof的问题。

//例子
Class type = ...
List<Class<? extends Father>> types = ...
M[] a = ...
for(Class type : types){
    if(type.isInstance(a[0]))
        语句;
}

3.递归计数

  A.isAssignableFrom(B)
  递归计数是相对于常规计数而言的。正常计数我们可以用动态的instanceof遍历数组实现对类型的计数。
  常规计数做法:
   【1】定义一个Map用于存储所有类型以及对应的计数。
   【2】遍历所有对象并获取它们的Class对象并与Map的所有对象进行A.isInstance(B)比较,并在Map中计数。

  递归计数做法:
  递归计数主要通过Class.isAssignableFrom()实现。我们注意到,计数时,如果当前对象是子类,那么它也一定是父类。因此在子类计数的同时,以检查父类的方式递归调用计数函数自身即可。isAssignableFrom()用于检测B是否在以A为基类的继承体系下。

//为某个对象计数,完成计数只需要对每个对象调用此函数即可。
public void countClass(Class<?> type){
    为当前类在Map中计数;
    Class<?> superClass = type.getSuperClass();
    if(superClass != null && baseType.isAssignableFrom(superClass)){
        //只要父类在基类的继承体系下
        countClass(superClass);        //递归计数
    }
}

三、反射及动态代理

1.反射,以及RTTI与反射的区别

  反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
  RTTI:在运行时,识别一个对象的类型。但是这个类型在编译时必须已知。
  反射:在运行时,识别一个对象的类型。但是这个类型在编译时不可获取。
RTTI与反射的区别

2.动态代理

(1)什么是代理

  代理模式:给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式。
  代理模式角色分为 3 种:

角色 功能
抽象主题角色 (Subject) 定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法
真实主题角色 (RealSubject) 真正实现业务逻辑的类
代理主题角色 (Proxy) 用来代理和封装真实主题

(2)动态代理

  代理是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了。(通常RealSubject与Proxy是耦合在一起的)
  动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件。(RealSubject与Proxy不再耦合,修改RealSubject不必修改Proxy)

  知识细节查询;
  《Java编程思想》14.7-14.8
  动态代理