获取Java运行时的类型信息两种方法:
- RTTI(Run-Time Type identification)
- Java反射机制
RTTI:在运行时,识别一个对象的类型。当从数组中取出元素时,会自动将结果转型回Shape。这是RTTI最基本的使用形式,因为在Java中,所有的类型转换都是在运行时进行正确检查的。
大部分代码尽可能少的了解对象的具体类型,而是只与对象家族中的一个通用表示打交道。
Java反射机制:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。
Class类是Java一个基础类,每装载一个新类的时候,Java虚拟机就会在Java堆中,创建一个Class实例,这个实例就代表这个Class类型,通过实例获取类型信息。该类中的一些方法如下:
Method[] getMethods() //返回实例中的所有方法
Field[] getFields() //返回实例中的成员变量
Constructor>[] getDeclaredConstructors() // 返回构造方法
Object类中的方法:
hashCode() / equals() / clone() / toString() / notify() / wait()
创建Class类的一个对象,返回一个类的引用
Class cls = Class.forName("Airplane")//返回一个类型
通过类的引用创建实例
cls.newlnstace(); //通过newlnstace创建实例,一般调用默认的构造函数
class Airplane {
public String toString() {
return("in airplane");
}
}
public class Createlnstance {
public static void main (String[] args) throws Exception{
Class c1 = null;
Object ap;
c1 = Class.forName("Airplane"); //创建Class类的一个对象,描述了类Airplane
System.out.print(c1);
ap = c1.newlnstance;//创建实例的另外一种办法
System.out.println(ap.toString());
}
}
Method类中 invoke 反射 invoke方法对带有指定参数的指定对象,调用由此Method对象表示的基础方法。
import java.lang.reflect.*;
public class ClassA {
public void add (Integer param1, lnteger param2) { //定义成员方法add
System.out.println(param1.intValue()+param2.intValue());
}
public void StringAdd(String abc) { //定义成员方法StringAdd
System.out.println("out"+abc);
}
public static void main(String[] args) {
try {
Method mth = ClassA.class.getMethod("add",new Class[] {lnteger.class,lnteger.class});
//声明方法类型的对象mth,属于类ClassA的方法
mth.invoke(ClassA.class.newInstance(),new lnteger(1), new lnteger(2));
//得到ClassA的实例,并传递参数,最后执行mth方法
Method mth1= ClassA.class.getMethod("StringAdd",new Class[] {Sting.class});
mth1.invoke(ClassA.class.newlnstance(),"--test");
}catch (Exception e) {}
}
}
代理模式:在某些情况下,一个客户不想或不能直接引用另一个对象,而代理对象可以在客户端或目标对象之间起到中介的作用。
如客户端由于权限原因不能访问目标对象。
代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。
代理模式一般涉及到的角色:
静态代理的例子:
//真实对象和代理对象的共同接口
abstract class Subject {
public abstrcat void request();
}
//真实角色
class RealSubject extends Subject {
public void request () {
System.out.println("From Real Subject");
}
}
//客户端
public class Client {
public static void main (String[] args) {
Subject subject = new ProxySubject();
subject.request();
}
}
//代理角色
class ProxySubject extends Subject {
//代理角色对象内部含有对真实对象的引用
private RealSubject realSubject;
@Override
public void request() {
//在真实角色操作之前所附加的操纵
preRequest();
if (null==realSubject) {
realSubject = new RealSubject();
}//真实角色所完成的事情。
realSubject.request();
//在真实角色操作之后所附加的操作
postRequest();
}
private void preRequest(){
System.out.println("Pre Request.");
}
prevate void postRequest() {
System.out.println("Post Request");
}
}
静态代理优缺点:
了。
~~
~~
java.lang.reflect.Proxy : Java动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。
//该方法用于获得指定代理对象所关联的调用处理器
static lnvocationHandle getlnvocationHandler(Objcet proxy)
//该方法用于获取关联于指定类装载器和一组接口的动态代理类的类对象
static Class getProxyClass (ClassLoader loader, Class[] interfaces)
//该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
//该方法用于为指定类装载器,一组接口,及调用处理器生成动态代理类实例
static Object newProxyInstance(ClassLoader loader, Class[] interface, lnvocationHandler h)
java.lang.reflect.InvocationHandler : 调用处理器接口,自定义了一个invoke方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。
Object invoke (Object proxy, Method method, Object[] args)
//该方法负责集中处理动态代理类上的所有方法调用。第一个参数是代理类实例,第二个参数是被调用的方法对象,第三个方法是调用参数。调用处理器根据这三个参数进行预处理或分派到委托实例上执行
Javad动态代理实例
抽象角色:
interface Subject {
public void request();
}
真实角色:实现了Subject的request()方法。
class RealSubject implements Subject {
public RealSubject() {}
public void request() {
System.out.println("From real subjcet.");
}
}
代理角色:必须继承lnvocaionHandler
import java.lang.reflect.Method;
import java.lang.reflect.lnvocationHandler;
class DynamicSubject implements InvocationHandler {
private Object sub;
public DynamicSubject() {}
public DynamicSubject(Object obj) {
sub=obj;
}
public Object invoke(Object proxy ,Method method, Obect[] args) throws Throwable {
System.out.println("before calling" + method);
method.invoke(sub,args);
System.out.println("after calling " + method);
return null;
}
}
客户端调用:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Client {static public void main (String[] args) throws Throws {
RealSubject rs = new ReallSubject(); //指定被代理类
InvocationHandler ds = new DynamicSubject(rs);
Class cls = rs.getClass();//以下是一次性生成代理
Subject subject = (Subject) Proxy.newProxylnstance(cls.getClassLoader(),cls.getInterfaces(),ds);
subject.request();
}
}
JVM类加载的种类:
JVM自带的默认加载器
类的加载方式:
类的加载步骤:
加载:
连接:包括 验证 准备 解析
类的初始化:
ClassLoader的加载顺序:
加载顺序:根加载器 =>扩展类加载器=>应用类加载器=>用户自定义加载器
如果到最后一层都再加载不了,就出现ClassNotFoundException异常。
ClassLoader加载Class的过程: