java反射

今天我们来看一下java反射机制。
反射机制是在运行状态中,对于任意一个类,都能够中的这个类的所有属性和方法,对于任意一个对象,都能够调用他的任意一个方法和属性
这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
在运行时生成任意一个对象所属的类
在运行时构造任意一个类的对象
在运行时判断任意一个类所具有的成员变量和方法
在运行时调用任意一个对象的方法
生成动态代理
一.关于反射,主要涉及的api主要有
java.lang.Class
java.lang.reflect.Method
java.lang.reflect.Field
java.lang.reflect.Constructor
接下来我们看一下这些api的使用

package wangcc.testapi;

public class User {
    private String name;
    private int age;

    public User() {
    }

    public User(String name) {
        this.name = name;
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void printName(String name) {
        System.out.println(name);

    }

    public void print() {
        System.out.println("Name:" + getName() + "Age:" + getAge());

    }

    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}
package wangcc.testapi;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class TestReflect {
    public static void main(String[] args) throws Exception {
        User user = new User();
        Class<?> clazz = user.getClass();
        Constructor<?> cons[] = clazz.getConstructors();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < cons.length; i++) {
            sb.append("cons[").append(i).append("](");
            Class<?> clazzs[] = cons[i].getParameterTypes();
            for (int k = 0; k < clazzs.length; k++) {
                if (k == clazzs.length - 1) {
                    sb.append(clazzs[k].getName()).append(")");
                } else {
                    sb.append(clazzs[k].getName()).append(",");
                }
            }
        }
        System.out.println(sb.toString());
        User user2 = (User) cons[0].newInstance("kobe", 39);
        System.out.println(user2.toString());
        User user3 = (User) cons[1].newInstance("kobe");
        System.out.println(user3.toString());
        // 获得类的全部属性
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            // 获得权限限定符
            int mod = fields[i].getModifiers();
            String strmod = Modifier.toString(mod);
            Class<?> type = fields[i].getType();
            System.out.println("限定符为" + strmod + "类型为:" + type.getName()
                    + "属性名:" + fields[i].getName());
        }
        Method[] methods = clazz.getMethods();
        for (int i = 0; i < methods.length; i++) {
            Method method = methods[i];
            System.out.println(method.getName());
            Class<?> returnType = method.getReturnType();
            System.out.println(returnType);
            Class<?> para[] = method.getParameterTypes();
            for (int k = 0; k < para.length; k++) {
                System.out.println(para[k].getName());
            }
            System.out.println("====");
        }
        Method method = clazz.getMethod("printName", String.class);
        method.invoke(user, "leborn");
        Field field = clazz.getDeclaredField("name");
        // 可以直接对 private 的属性赋值
        field.setAccessible(true);
        field.set(user, "ddddgadgleg");
        System.out.println(user.getName());
    }

}

我们这里再讲解一下通过反射对其他类中的方法的调用

    Method method = clazz.getMethod("printName", String.class);
        method.invoke(user, "leborn");

首先关于如何得到一个类的class对象,我们有多种方法

package wangcc.testapi;

/**
 * @ClassName: TestGetClassObject
 * @Description: TODO(创建Class类对象实例)
 * @author wangcc
 * @date 2017年3月4日 下午9:07:26
 * 
 */
public class TestGetClassObject {

    public static void main(String[] args) throws ClassNotFoundException {
        // TODO Auto-generated method stub
        Class<?> clazz1 = TestGetClassObject.class;
        Class<?> clazz2 = new TestGetClassObject().getClass();
        // 参数为类的完全限定名
        Class<?> clazz3 = Class.forName("wangcc.testapi.TestGetClassObject");
        System.out.println(clazz1.getName());
        System.out.println(clazz2.getName());
        System.out.println(clazz3.getName());
    }
}

可以通过new 出对象之后在调用getClass()方法得到这个对象的class对象实例
也可以直接在类名后加上.classs
一般我们用Class api中的Class.forname()方法来完成class对象实例的获取。
(在应用中我们可以将完全限定名,方法名等存储到数据库中,然后在数据库中查找,然后通过class.forname()得到类的class对象clazz,通过clazz.getMethods()可以获得所有的方法,通过clazz.newInstance()可以得到一个类的对象实例,如同于用一个无参构造函数new出一个实例,在这里多说一句,当一个类有显示的有参构造函数时,我们需要显式的加上无参构造函数)
还有一点我们需要注意,再调用clazz. getConstructors()时我们只返回修饰符为public 的公共构造方法,不会返回private修饰的,这个你可以做个试验看一下,我之前并没有注意,仔细翻看了API后才注意到,还是需要多看api.在我们得到Constructor对象后,我们就可以调用这个api的newInstance(Object… initargs)
来获取类实例了,参数列表为相应的构造方法的参数列表。
说的有点远了,我们回头来看一下
Method method = clazz.getMethod(“printName”, String.class);
Class API中的getMethod方法时获取某个特定的Method对象的方法
第一个参数名为MethodName,之后的参数列表为方法参数的类型的class对象,
获得Method对象之后
我们要调用Method对象中一个非常重要的方法:invoke()
method.invoke(user, “leborn”);
我们来看一下api中对invoke的说明
invoke
public Object invoke(Object obj,
Object… args)
throws IllegalAccessException,
IllegalArgumentException,
InvocationTargetException对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。
如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null。

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 或 null。

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。
如果底层方法是静态的,并且尚未初始化
如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不 被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null。
二.最后我们来说一下反射的应用
反射的重要应用,动态代理
首先为什么要用动态代理
动态代理用于方法的增强,他可以在不影响原程序代码的情况下改变指定方法的运行情况,增加运行前后的处理
常见用于struts的拦截器,Spring AOP
然后我们说一下上面是动态代理
其实往简单的说,动态代理技术就是用来产生一个对象的代理对象的。
在这里需要明确关于代理对象的概念:
代理对象的存在价值主要是用于拦截对真实业务对象的访问

代理对象应该具有和目标对象相同的方法

这也是一种设计模式
代理模式
有静态代理和动态代理
关于设计模式,在以后会抽空写,主要也是关于大话设计模式的读书笔记吧
实现jdk动态代理
我们需要了解一个类Proxy
Proxy 提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
我们主要关注他的一个静态方法
newProxyInstance
public static Object newProxyInstance(ClassLoader loader,
Class

package wangcc.dynamicproxy;

public interface Subject {
    public String getName(String name);
}
package wangcc.dynamicproxy;

public class RealSubject implements Subject {

    @Override
    public String getName(String name) {
        // TODO Auto-generated method stub
        String retStr = "kobe" + name;
        return retStr;
    }

}
package wangcc.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class MySubjectHandler implements InvocationHandler {
    private RealSubject obj;

    /**
     * @Title: bind
     * @Description: TODO(生成代理对象)
     * @param @param obj
     * @param @return 设定文件
     * @return Object 返回类型
     * @throws
     */
    public Subject bind(RealSubject obj) {
        this.obj = obj;
        return (Subject) Proxy.newProxyInstance(
                obj.getClass().getClassLoader(),
                obj.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        // TODO Auto-generated method stub
        String methodName = method.getName();

        if (methodName.equals("getName")) {

            args[0] = "leborn";

            return method.invoke(obj, args);
        }
        return method.invoke(obj, args);
    }

}
package wangcc.dynamicproxy;

public class Test {
    public static void main(String[] args) {
        MySubjectHandler myHandler = new MySubjectHandler();
        Subject subject = (Subject) myHandler.bind(new RealSubject());
        String name = subject.getName("bryant");
        System.out.println(name);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值