- 在向List
中插入Shape对象时,list把每个对象作为Object类型存储,取出时自动转换为Shape类型,类型转换正确性是在运行时动态检查的,编译时由Java容器和范型机制保证,运行时,由类型转换确保 - Class对象:
- 每个Java类都有一个Class对象,所有类都是第一次使用加载到JVM中的,当程序创建第一个对类的静态成员引用时,回家在这个类(由此证明构造方法是静态方法,即使没有static关键字),Java程序并非在开始运行之前完全被加载,各个部分是在需要时才被加载,static成员初始化是在类第一次加载时执行
- forName()是Class的静态成员,用于获取Class对象的引用,如果这个类没有被加载,就会加载;如果已经有了一个对象,想要获得这个对象的Class对象引用,可以使用getClass()方法,
- Class类中的一些静态方法
- getName(),getSimpleName() 得到类名
- getSuperclass() 得到直接基类
- Class.getInterfaces()方法返回Class对象的数组,这些对象代表的是某个Class对象所包含的接口。
- newInstance() 虚拟构造器,会得到一个Object引用,指向具体类型的对象,该类必须具有默认构造方法
- 类字面常量:如Toy.class,替换forName()方法,在编译期就会受到检查
- 步骤:
- 加载:类加载器执行,创建一个Class对象
- 链接:为静态域分配空间,创建对其他类的引用
- 初始化:初始化其超类,执行静态初始化类
- 当使用类字面常量来获得Class对象引用时,不会对类的引用初始化,当访问类中成员时才链接和初始化
- 步骤:
- 类型转换检查:
- a instanceof b:返回一个boolean型变量
- Class.isInstance():动态测试对象
- 等价性:
- instanceof,isInstance():考虑了继承
- equals(),==:未考虑继承
- 反射:
- Field,Method,Constructor类表示未知类中对应的成员
- 使用反射时,JVM检查这个类,需要先加载这个类,因此.class文件必须是可获得的
- Class的getMethods()和getConstructors()方法返回Method和Constructor对象数组,这两个类都提供了深层方法,用以解析其对象所代表的的方法,并获取其名字,输入参数及返回值
- 动态代理:http://www.cnblogs.com/xiaoluo501395377/p/3383130.html
- 每一个动态代理类都必须要实现InvocationHandler这个接口,,这个接口的唯一一个方法 invoke 方法,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用:
Object invoke(Object proxy, Method method, Object[] args) throws Throwable
- proxy: 指代我们所代理的那个真实对象
- method: 指代的是我们所要调用真实对象的某个方法的Method对象
- args: 指代的是调用真实对象某个方法时接受的参数
- Proxy这个类的作用就是用来动态创建一个代理对象的类,它提供了许多的方法,但是我们用的最多的就是 newProxyInstance 这个方法:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException
- loader: 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
- interfaces: 一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
- h: 一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
- 使用:
public class Client
- 每一个动态代理类都必须要实现InvocationHandler这个接口,,这个接口的唯一一个方法 invoke 方法,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用:
{
public static void main(String[] args)
{
// 我们要代理的真实对象
Subject realSubject = new RealSubject();
// 我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
InvocationHandler handler = new DynamicProxy(realSubject);
/*
* 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
* 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
* 第二个参数realSubject.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
* 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
*/
Subject subject = (Subject)Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject
.getClass().getInterfaces(), handler);
System.out.println(subject.getClass().getName());
subject.rent();
subject.hello("world");
}
}
```