Java是如何让我们在运行时识别对象和类的信息的。主要有两种方式:
(1)RTTI,Runtime Type Information,运行时类型信息,它假定在编译时已经知道了所有的类型
(2)反射,它允许我们在运行时发现和使用类的信息
14.1 为什么需要RTTI
Shapes
abstract class Shape {
void draw() {
System.out.println(this + ".draw()!");
}
abstract public String toString();
}
class Circle extends Shape{
@Override
public String toString() {
return "Circle";
}
}
class Square extends Shape{
@Override
public String toString() {
return "Square";
}
};
class Shapes {
public static void chapter14_1() {
List<Shape> shapeList = Arrays.asList(new Circle(),new Square()); //(1)upcast
for(Shape s:shapeList) { //(2)RTTI Object->Shape
s.draw(); //(3)polymorphic
}
}
}
(1)向上转型
(2)容器会自动将Object转型为Shape,这里是RTTI
(3)多态机制
14.6 反射
RTTI和反射的真正区别是,对于RTTI来说,编译器在编译时打开和检查.class文件;对于反射来说,.class文件在编译时是不可获取的,在运行时打开和检查.class文件。
ShowMethods
class ShowMethods {
public ShowMethods() {
System.out.println("test");
}
public static void chapter14_6() {
try {
Class<?> c = Class.forName("thinkinjava.hyh.ShowMethods");
Method[] methods = c.getMethods();
Constructor[] ctors = c.getConstructors();
System.out.println("methods:");
for(Method method:methods) {
System.out.println(method.toString());
}
System.out.println("ctors:");
for(Constructor constructor:ctors) {
System.out.println(constructor.toString());
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
类方法提取器
14.7 动态代理
代理模式:为了提供额外的或不同的操作,而插入的用来代替实际对象的对象。
SimpleProxyDemo
interface Interface {
void doSomething();
}
class RealObject implements Interface {
@Override
public void doSomething() {
System.out.println("doSomething");
}
}
class SimpleProxy implements Interface {
private Interface proxy;
public SimpleProxy(Interface inter) {
proxy = inter;
}
@Override
public void doSomething() {
System.out.println("SimpleProxy:");
proxy.doSomething();
}
}
class SimpleProxyDemo{
public static void consumer(Interface inter) {
inter.doSomething();
}
public static void chapter14_7() {
consumer(new RealObject());
consumer(new SimpleProxy(new RealObject()));
}
}
SimpleDynamicProxy
class DynamicProxyHandler implements InvocationHandler {
private Object real;
public DynamicProxyHandler(Object real) {
this.real = real;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy:" + proxy.getClass());
System.out.println("method:" + method);
System.out.println("args:" + args);
if(args != null) {
for(Object arg:args) {
System.out.println("arg:" + arg);
}
}
return method.invoke(real,args);
}
}
class SimpleDynamicProxy {
public static void consumer(Interface inter){
inter.doSomething();
}
public static void chapter14_7() {
RealObject real = new RealObject();
consumer(real);
Interface proxy = (Interface) Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(real));
consumer(proxy);
}
}
动态地创建代理(不需要有SimpleProxy代理类)并动态地处理对所代理方法的调用,在动态代理上所做的所有调用都会被重定向到单一的调用处理器上。
通过调用静态方法Proxy.newProxyInstance()可以创建动态代理,这个方法需要得到一个类加载器,一个你希望该代理实现的接口列表,和InvocaitionHandler接口的一个实现。