14 类型信息

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接口的一个实现。

猜你喜欢

转载自blog.csdn.net/u012906122/article/details/113908749
14