Java 反射机制

Java的反射机制是在编译时并不确定是哪个类被加载了,而是在程序运行的时候才加载、探知、自审。使用的是在编译期并不知道的类。这样的编译特点就是java反射。反射可以在运行时获取任意 Class 或 Object 内部所有的成员变量、成员方法、构造函数和 Annotation。

本文中用到的类:

StaticMethod

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface StaticMethod  {

}

UserInfo

public class UserInfo {

    private String userName;
    private int userId;

    public UserInfo(String userName, int userId) {
        this.userName = userName;
        this.userId = userId;
    }

    @StaticMethod
    public String getUserName() {
        System.out.println("getUserName");
        return this.userName;
    }

    @StaticMethod
    public static void staticMethod(String userName, int id) {
        System.out.println("static method invoked:" + userName);
    }

}
public class Reflect {

    public static void main(String[] strings) {
//        getFields(UserInfo.class);
//        getMethod(UserInfo.class);
//        getConstruction(UserInfo.class);
//        getFieldValue(new UserInfo("owen", 1));
//        invokeMethod();
    }

    private static void getFields(Class userInfoClass) {
        Field[] fields = userInfoClass.getDeclaredFields();
        for(Field field : fields) {
            String fieldString = "";
            fieldString += Modifier.toString(field.getModifiers()) + " ";
            fieldString += field.getType().getSimpleName() + " ";
            fieldString += field.getName();
            fieldString += ";";
            System.out.println(fieldString);
        }
    }

    private static void getMethod(Class userInfoClass) {
        Method[] methods = userInfoClass.getDeclaredMethods();
        for (Method method : methods) {
            String methodString = Modifier.toString(method.getModifiers()) + " " ; // private static
            methodString += method.getReturnType().getSimpleName() + " "; // void
            methodString += method.getName() + "("; // staticMethod
            Class[] parameters = method.getParameterTypes();
            for (Class parameter : parameters) {
                methodString += parameter.getSimpleName() + " "; // String
            }
            methodString += ")";
            System.out.println(methodString);
        }
    }

    private static void getConstruction(Class userInfoClass) {
        Constructor[] constructors = userInfoClass.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            String s = Modifier.toString(constructor.getModifiers()) + " ";
            s += constructor.getName() + "(";
            Class[] parameters = constructor.getParameterTypes();
            for (Class parameter : parameters) {
                s += parameter.getSimpleName() + ", ";
            }
            s += ")";
            System.out.println(s);
        }
    }

    private static void getFieldValue(UserInfo userInfo) {
        try {
            Field field = UserInfo.class.getDeclaredField("userName");
            field.setAccessible(true);
            String str = (String) field.get(userInfo);
            System.out.print(str);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void invokeMethod() {
        try {
            Method[] methods = UserInfo.class.getDeclaredMethods(); // 获取所有成员方法
            for (Method method : methods) {
                if (method.isAnnotationPresent(StaticMethod.class)) { // 判断是否被 @Invoke 修饰
                    if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法
                        method.invoke(null, "owen", 12); // 直接调用,并传入需要的参数 devName
                    } else {
                        Class[] params = {String.class, int.class};
                        Constructor constructor = UserInfo.class.getDeclaredConstructor(params); // 获取参数格式为 String,long 的构造函数
                        Object userBean = constructor.newInstance("owen", 11); // 利用构造函数进行实例化,得到 Object
                        if (Modifier.isPrivate(method.getModifiers())) {
                            method.setAccessible(true); // 如果是 private 的方法,需要获取其调用权限
                        }
                        method.invoke(userBean); // 调用 method,无须参数
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

1、打印成员变量

Java 里提供了 Field 这个类来表示成员变量,提供了 clazz.getDeclaredFields() 来获取一个类内部声明的所有变量。因此,可以利用下面的代码获取 UserInfo 内部所有的成员变量。

代码如下:

private static void getFields(Class userInfoClass) {
    Field[] fields = userInfoClass.getDeclaredFields();
    for(Field field : fields) {
        String fieldString = "";
        fieldString += Modifier.toString(field.getModifiers()) + " ";
        fieldString += field.getType().getSimpleName() + " ";
        fieldString += field.getName();
        fieldString += ";";
        System.out.println(fieldString);
    }
}

2、打印成员方法

可以通过 Method[] methods = UserInfo.class.getDeclaredMethods(); 获得所有的成员方法

代码如下:

private static void getMethod(Class userInfoClass) {
    Method[] methods = userInfoClass.getDeclaredMethods();
    for (Method method : methods) {
        String methodString = Modifier.toString(method.getModifiers()) + " " ; // private static
        methodString += method.getReturnType().getSimpleName() + " "; // void
        methodString += method.getName() + "("; // staticMethod
        Class[] parameters = method.getParameterTypes();
        for (Class parameter : parameters) {
            methodString += parameter.getSimpleName() + " "; // String
        }
        methodString += ")";
        System.out.println(methodString);
    }
}

3、打印构造函数:

Java 里提供了 Constructor 来表示构造函数

代码如下:

private static void getConstruction(Class userInfoClass) {
    Constructor[] constructors = userInfoClass.getDeclaredConstructors();
    for (Constructor constructor : constructors) {
        String s = Modifier.toString(constructor.getModifiers()) + " ";
        s += constructor.getName() + "(";
        Class[] parameters = constructor.getParameterTypes();
        for (Class parameter : parameters) {
            s += parameter.getSimpleName() + ", ";
        }
        s += ")";
        System.out.println(s);
    }
}

4、获取对象中某个变量的值

private static void getFieldValue(UserInfo userInfo) {
    try {
        Field field = UserInfo.class.getDeclaredField("userName");
        field.setAccessible(true);
        String str = (String) field.get(userInfo);
        System.out.print(str);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

5、调用 Class 内部的用 @Invoke 修饰的方法

可以利用 class.getDeclaredMethods() 获取一个类内部所有成员方法,然后:
判断这个方法是否被 @Invoke 修饰
如果修饰,判断这个方法是不是 static 的
如果是 static,则可以直接用 class 调用
如果不是 static,那就需要实例化一个对象来调用
如果这个方法是 private 的,要记得 setAccessible(true)。
代码如下:

private static void invokeMethod() {
    try {
        Method[] methods = UserInfo.class.getDeclaredMethods(); // 获取所有成员方法
        for (Method method : methods) {
            if (method.isAnnotationPresent(StaticMethod.class)) { // 判断是否被 @Invoke 修饰
                if (Modifier.isStatic(method.getModifiers())) { // 如果是 static 方法
                    method.invoke(null, "owen", 12); // 直接调用,并传入需要的参数 devName
                } else {
                    Class[] params = {String.class, int.class};
                    Constructor constructor = UserInfo.class.getDeclaredConstructor(params); // 获取参数格式为 String,long 的构造函数
                    Object userBean = constructor.newInstance("owen", 11); // 利用构造函数进行实例化,得到 Object
                    if (Modifier.isPrivate(method.getModifiers())) {
                        method.setAccessible(true); // 如果是 private 的方法,需要获取其调用权限
                    }
                    method.invoke(userBean); // 调用 method,无须参数
                }
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值