java反射机制(Reflection)
java类型信息
1..获取java运行时的类型信息有两种方法
1)RTTI
2)java反射机制
RTTI
1.为什么需要RTTI
1)在运行时,识别一个对象的类型
2)当从数组中取出元素时,会自动将结果转型回Shape。这是RTTI最基本的使用形式,
因为在java中,所有的类型转换都是在运行时进行正确性检查的
3)大部分代码尽可能少地了解对象的具体类型,而是只与对象家族中的一个通用表示方式打交道
java反射机制的定义
1.java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;
对于任意一个对象,都能够调用它的任意方法和属性;
这种动态获取信息以及动态调用对象的功能称为java语言的反射机制
类Class
1.Class类是java一个基础类,每装载一个新类的时候,java虚拟机就会在java堆中,
创建一个Class的实例,这个实例就代表这个Class类型,通过实例获取类型信息。
该类中的一些方法如下:
Method[] getMethods()
Field[] getFields()
Constructor<?>[] getDeclaredConstructors()
2.Object类中的方法
hashCode()
equals()
clone()
toString()
notify()
wait()
利用Class类来创建实例
1.创建Class类的一个对象,返回一个类的引用
Class cls=Class.forName("Aidplane");//返回一个类的实例
2.通过类的引用创建实例
cls.newInstace();//通过newInstace创建实例,一般调用默认的构造函数
java反射的例子--Method类的invoke
1.Method类中invoke反射
invoke方法对带有指定参数的指定对象,调用由此Method对象表示的基础方法
代理模式
1.在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和
目标对象之间起到中介的作用
2.代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。
代理模式一般涉及到的角色
1.抽象角色:声明真实对象和代理对象的共同接口。
2.代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象
提供与真实对象相同的接口以便在任何时刻都能够代替真实对象。
同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装,
3.真实角色:代理对象所代表的真实对象,是我们最终要引用的对象
静态代理例子
静态代理的优缺点
1.优点
1)业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点
2.缺点
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为
每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了
动态代理
1.java.lang.reflect.Proxy
这是java动态代理机制的主类,他提供了一组静态方法来为一组接口动态地生成代理类及其对象
//该方法用于获取指定代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)
//该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass(ClassLoader,Class[] interfaces)
//该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
//该方法用于为指定类装载器,一组接口及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader,Class[] interfaces,InvocationHandler h)
2.java.lang.reflect.InvocationHandler
这是调用处理器接口,它自定义了一个invoke方法,用于集中处理在动态代理类对象上的方法调用,
通常在该方法中实现对委托类的代理访问
Object invoke(Object proxy,Method method,Object[] args)
//该方法负责集中处理动态代理类上的所有方法调用
//第一个参数是代理类实例,第二个参数是被调用的方法对象
//第三个方法是调用参数。
//调用处理器根据这三个参数进行预处理或分派到委托类实例上执行
动态代理实例
动态代理的特点
1.包:如果所代理的接口都是public的,那么它将被定义在顶层包(即包路径为空),
如果所代理的接口中有非public的接口,那么它将被定义在该接口所在包,
这样设计的目的是为了最大程度的保证动态代理类不会因为包管理的问题而无法被成功定义并访问
2.类修饰符:该代理类具有final和public修饰符,意味者它可以被所有的类访问,但是不能被再度继承
3.类名:格式是“$ProxyN”,代表Proxy类第N次生成的动态代理类,提高了代理类的创建效率
动态代理的优点和缺点
1.优点:动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用
处理器一个集中的方法中处理(InvocationHandler.invoke)这样,在接口方法数量比较多
的时候,可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转
2.缺点:Proxy已经设计的非常优美,但是还是有一点的小小遗憾,那就是它始终无法
摆脱仅仅支持interface代理的弱点
JVM类加载的种类
1.JVM自带的默认加载器
1)根类加载器:bootstrap,由C++编写,所有java程序无法获得
2)扩展类加载器:由java编写
3)系统类,应用类加载器:由java编写
2.用户自定义的类加载器:
java.lang.ClassLoader的子类,用户可以定制类的加载方式。
每一个类都包含了加载他的ClassLoader的一个引用--getClassLoader().
如果返回的是null,证明加载他的ClassLoader是根加载器bootstrap
类的加载方式
1.本地编译好的class中直接加载
2.网络加载:java.net.URLClassLoader可以加载url指定的类
3.从jar,zip等等压缩文件加载类,自动解析jar文件找到class文件去加载
4.从java源代码文件动态编译成为class文件
类加载的步骤
1.加载
2.连接,包括以下小步骤
验证,准备,解析
3.类的初始化
ClassLoader的加载顺序
1.加载顺序:
根加载器->扩展类加载区->应用类加载器->用户自定义类加载器
如果到最后一层都加载不了就出现ClassNotFoundException异常
ClassLoader加载Class的过程
第1步:检测此Class是否载入过(即在cache中是否有此Class),如果有跳到第8步,如果没有到第2步
第2步:如果parent classloader不存在(没有parent,那parent一定是bootstrap classloader了),则跳到第4步
第3步:请求parent classloader载入,如果成功到第8步,不成功到第5步
第4步:请求jvm从bootstrap classloader中载入,如果成功到第8步
第5步:寻找Class文化(从与此classloader相关的类路径中寻找)。如果找不到则到第7步.
第6步:从文件中载入Class,到第8步
第7步:抛出ClassNotFoundException
第8步:返回Class