java经典面试题(通过输入方法名或者方法名上注解的value值通过反射动态调用该方法)

问题描述

现存在一个如下类

package com.qianfeng.workone.ReflectWork01;


import com.qianfeng.workone.ReflectWork01.annotation.Process;

public class Calculate {

    @Process("添加")
    public void add() {
        System.out.println("add 方法被调用了");
    }

    public void edit() {
        System.out.println("编辑方法被调用了");
    }

    @Process("删除")
    public void delete() {
        System.out.println("删除方法被调用了");
    }
}

如何通过反射,输入该方法名或者直接输入注解中的value值就可直接调用对应方法

解题思路

基础思路:
要调用方法就得获得方法对象
要获得方法对象就得获得字节码对象,和实例对象
获得以上条件时候就可以通过方法名调用该方法

但是现在存在一个问题就是,如何通过注解的value值来绑定对应的方法从而实现调用?
解决办法就是:首先获得方法对象数组,对每一个数组对象通过isAnnotationPresent()判断是否存在注解,如果存在注解,那么就将注解的value值与输入值进行比较,成功则调用,失败则判断是否为方法名,成功则调用,失败则提示不存在该方法。

高级思路:
在解决上述问题的基础上有两个问题值得考虑:

  1. 如果增加方法名或者增加注解,源代码能否不变
  2. 如果换了一个类,在源代码不改变的情况下,能否实现

为解决以上的两个为题,那么就需要封装一个分析类
分析类如何设计?
属性:
Class<?> aClass 获取传入类的字节码对象
private Object obj 为之后的方法调用创建一个公共对象
private Map<String, Method> indeedMethod = new HashMap<>(); 此map集合用于存储方法名和该方法对象
private Map<String, Method> aliasMethod = new HashMap<>(); 此map集合用于存储注解名和该方法名

方法:
public void invoke() 通过字节码对象来初始化indeedMethod和aliasMethed
public void ivk(String methodName) 通过传入的字符串来调用对应方法
ivk()方法思路:首先通过methodName来获取aliasMethed中的value如果存在,则直接通过此value来结合indeedMethed获得方法对象从而调用,如果不存在,那么就通过indeedMethed判断是否存在方法对象,存在则调用,不存在则提示该方法不存在;

代码示例

Process注解

package com.qianfeng.workone.ReflectWork01.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)  // 运行期已然保留
@Target({ElementType.METHOD})  // 只能作用在方法上
public @interface Process {
    String value();
}

Parser类

package com.qianfeng.workone.ReflectWork01;

import com.qianfeng.workone.ReflectWork01.annotation.Process;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class Parser {

    //获取类的字节码对象
    private Class<?> aClass;

    //公共调用对象
    private Object obj;

    //方法名称和方法对象的map集合(indeed真正的)
    private Map<String, Method> indeedMethod = new HashMap<>();

    //方法别名和方法名的map集合()(alias别名)
    private Map<String,String> aliasMethod = new HashMap<>();

    //构造方法
    public Parser(Class<?> aClass){
        this.aClass = aClass;
        this.invoke();
    }

    //invoke调用
    public void invoke(){
        try {
            obj = aClass.newInstance();
            Method[] methods = aClass.getDeclaredMethods();
            for (Method method : methods) {
                String name = method.getName();
                indeedMethod.put(name,method);
                Process annotation = method.getAnnotation(Process.class);
                if(annotation != null){
                    String value = annotation.value();
                    aliasMethod.put(value,name);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    public void ivk(String methodName){
        String realMethodName = aliasMethod.get(methodName);
        if(realMethodName != null){
            Method method = indeedMethod.get(realMethodName);
            try {
                method.invoke(obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            Method method = indeedMethod.get(methodName);
            if(method != null){
                try {
                    method.invoke(obj);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                System.out.println(methodName + ";此方法不存在!");
            }
        }
    }
}

Test01类

package com.qianfeng.workone.ReflectWork01;

import java.util.Scanner;

public class Test01 {
    public static void main(String[] args) throws Exception {
        Scanner scanner = new Scanner(System.in);

        Parser parser = new Parser(Calculate.class);

        while(true) {
            System.out.print("请输入要执行的方法:");
            String value = scanner.next();  // edit
            parser.ivk(value);

        }
        
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值