方法处理和变量处理的练习
练习要求
使用控制台传入一个类名 方法名 返回值类型 把对应的方法,变量打印出来,输入错误有提示信息
使用MethodHandle和VarHandle获取目标类中的实例变量,实例方法和类变量,类方法的信息
效果如下:
1.获取方法
2.获取变量
1
请输入方法名
输入exit或退出,返回上一步
sdfghj
请输入正确的方法名,只可为setAge或setName
setName
带参数的实例方法:小马
小马你好
setAge
不带参数的类方法,年龄是:1
hello baby!
退出
1.获取方法
2.获取变量
2
请输入变量名
dfghjk
请输入正确的变量名,只可为name或age
ghj
请输入正确的变量名,只可为name或age
age
类变量age值为:28
name
实例变量name值为:微笑
exit
1.获取方法
2.获取变量
退出
程序结束,欢迎下次使用
实现思路:先创建一个类变量和一个实例变量,再创建类方法和实例方法,分别为获取方法和获取变量抽象成两个方法来实现,最后在main方法中获取Scanner,调用这两个方法,即可完成,代码如下:
package seven.five;
import java.util.Scanner;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.VarHandle;
/**
* 用控制台控制类方法,实例方法,类变量,实例变量的使用
*
* @author 张林琛<br>
* @date 2019/12/14 08:25:53
* @version 1.0
*/
public class HandleTest {
// 实例变量
public String name;
// 类变量
public static int age;
/**
* 不带参数的类方法
*/
public static void setAge() {
age++;
System.out.println("不带参数的类方法,年龄是:" + age);
System.out.println("hello baby!");
}
/**
* 带参数和返回值的实例方法
*
* @param name 传入的名字
* @return 返回结果
*/
public String setName(String name) {
System.out.println("带参数的实例方法:" + name);
return name + "你好";
}
/**
* 调用类方法和实例方法
*
* @param sc 扫描器对象
*/
public static void callMethod(Scanner sc) throws Throwable {
System.out.println("请输入方法名\n输入exit或退出,返回上一步");
while (sc.hasNextLine()) {
String str = sc.nextLine();
// 判断调用的是哪个方法
if (str.equals("setAge")) {
// 定义返回值为void,不带形参的方法类型
MethodType mt = MethodType.methodType(void.class);
// 使用MethodHandles.lookup()的findStatic()获取类方法
MethodHandle mh = MethodHandles.lookup().findStatic(HandleTest.class, "setAge", mt);
// 通过MethodHandle执行方法
mh.invoke();
} else if (str.equals("setName")) {
// 使用MethodHandles.Lookup的findVirtual获取实例方法
MethodHandle mh2 = MethodHandles.lookup().findVirtual(HandleTest.class, "setName",
// 指定获取返回值类型为String,形参为String的方法类型
MethodType.methodType(String.class, String.class));
// 通过MethodHandle执行方法,传入主调对象和参数
System.out.println(mh2.invoke(new HandleTest(), "小马"));
continue;
} else if (str.equals("退出") || str.equals("exit")) {
return;
} else {
System.out.println("请输入正确的方法名,只可为setAge或setName");
}
}
}
/**
* 调用变量
*
* @param sc 扫描器对象
*/
public static void callVar(Scanner sc) throws NoSuchFieldException, IllegalAccessException {
System.out.println("请输入变量名");
while (sc.hasNextLine()) {
String str = sc.nextLine();
// 判断调用的是哪个方法
if (str.equals("name")) {
// 用findVarHandle方法获取HandleTest类中名为name,类型为String的实例变量
VarHandle vh = MethodHandles.lookup().findVarHandle(HandleTest.class, "name", String.class);
// 创建当前类对象
HandleTest ht = new HandleTest();
// 为实例变量赋值
vh.set(ht, "微笑");
// 输出实例变量
System.out.println("实例变量name值为:" + ht.name);
} else if (str.equals("age")) {
// 用findVarHandle方法获取HandleTest类中名为age,类型为int的类变量
VarHandle vh1 = MethodHandles.lookup().findStaticVarHandle(HandleTest.class, "age", int.class);
// 通过VarHandle设置指定类变量的值
vh1.set(28);
// 输出User的MAX_AGE类变量
System.out.println("类变量age值为:" + HandleTest.age);
} else if (str.equals("退出") || str.equals("exit")) {
return;
} else {
System.out.println("请输入正确的变量名,只可为name或age");
}
}
}
/**
* 程序入口
*
* @param args
* @throws Throwable
*/
public static void main(String[] args) throws Throwable {
Scanner sc = new Scanner(System.in);
System.out.println("1.获取方法\n2.获取变量");
while (sc.hasNextLine()) {
String str = sc.nextLine();
if (str.equals("1")) {
// 如果输入1,则调用获取方法
HandleTest.callMethod(sc);
} else if (str.equals("2")) {
// 如果输入2,则调用获取变量
HandleTest.callVar(sc);
} else if (str.equals("退出") || str.equals("exit")) {
System.out.println("程序结束,欢迎下次使用");
break;
} else {
System.out.println("请输入对应的选项");
}
System.out.println("1.获取方法\n2.获取变量");
}
}
}
这是对MethodHandle和VarHandle最简单的用法,更多用法请参考API!