分析方法四要素
我们先来看一下,不使用反射机制调用一个方法需要几个要素的参与。
有一个这样的类:
package com.powernode.reflect; /** * @author 动力节点 * @version 1.0 * @className SystemService * @since 1.0 **/ public class SystemService { public void logout(){ System.out.println("退出系统"); } public boolean login(String username, String password){ if ("admin".equals(username) && "admin123".equals(password)) { return true; } return false; } }
编写程序调用方法:
package com.powernode.reflect; /** * @author 动力节点 * @version 1.0 * @className ReflectTest01 * @since 1.0 **/ public class ReflectTest01 { public static void main(String[] args) { // 创建对象 SystemService systemService = new SystemService(); // 调用方法并接收方法的返回值 boolean success = systemService.login("admin", "admin123"); System.out.println(success ? "登录成功" : "登录失败"); } }
执行结果:
通过以上第16行代码可以看出,调用一个方法,一般涉及到4个要素:
调用哪个对象的(systemService)
哪个方法(login)
传什么参数("admin", "admin123")
返回什么值(success)
获取Method
要使用反射机制调用一个方法,首先你要获取到这个方法。
在反射机制中Method实例代表的是一个方法。那么怎么获取Method实例呢?
有这样一个类:
package com.powernode.reflect; /** * @author 动力节点 * @version 1.0 * @className SystemService * @since 1.0 **/ public class SystemService { public void logout(){ System.out.println("退出系统"); } public boolean login(String username, String password){ if ("admin".equals(username) && "admin123".equals(password)) { return true; } return false; } public boolean login(String password){ if("110".equals(password)){ return true; } return false; } }
我们如何获取到 logout()、login(String,String)、login(String) 这三个方法呢?
要获取方法Method,首先你需要获取这个类Class。
Class clazz = Class.forName("com.powernode.reflect.SystemService");
当拿到Class之后,调用getDeclaredMethod()方法可以获取到方法。
假如你要获取这个方法:login(String username, String password)
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);
假如你要获取到这个方法:login(String password)
Method loginMethod = clazz.getDeclaredMethod("login", String.class);
获取一个方法,需要告诉Java程序,你要获取的方法的名字是什么,这个方法上每个形参的类型是什么。这样Java程序才能给你拿到对应的方法。
这样的设计也非常合理,因为在同一个类当中,方法是支持重载的,也就是说方法名可以一样,但参数列表一定是不一样的,所以获取一个方法需要提供方法名以及每个形参的类型。
假设有这样一个方法:
public void setAge(int age){ this.age = age; }
你要获取这个方法的话,代码应该这样写:
Method setAgeMethod = clazz.getDeclaredMethod("setAge", int.class);
其中setAge是方法名,int.class是形参的类型。
如果要获取上面的logout方法,代码应该这样写:
Method logoutMethod = clazz.getDeclaredMethod("logout");
因为这个方法形式参数的个数是0个。所以只需要提供方法名就行了。你学会了吗?
调用Method
要让一个方法调用的话,就关联到四要素了:
调用哪个对象的
哪个方法
传什么参数
返回什么值
package com.powernode.reflect; /** * @author 动力节点 * @version 1.0 * @className SystemService * @since 1.0 **/ public class SystemService { public void logout(){ System.out.println("退出系统"); } public boolean login(String username, String password){ if ("admin".equals(username) && "admin123".equals(password)) { return true; } return false; } public boolean login(String password){ if("110".equals(password)){ return true; } return false; } }
假如我们要调用的方法是:login(String, String)
第一步:创建对象(四要素之首:调用哪个对象的)
Class clazz = Class.forName("com.powernode.reflect.SystemService"); Object obj = clazz.newInstance();
第二步:获取方法login(String,String)(四要素之一:哪个方法)
Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class);
第三步:调用方法
Object retValue = loginMethod.invoke(obj, "admin", "admin123");
解说四要素:
哪个对象:obj
哪个方法:loginMethod
传什么参数:"admin", "admin123"
返回什么值:retValue
package com.powernode.reflect; import java.lang.reflect.Method; /** * @author 动力节点 * @version 1.0 * @className ReflectTest02 * @since 1.0 **/ public class ReflectTest02 { public static void main(String[] args) throws Exception{ Class clazz = Class.forName("com.powernode.reflect.SystemService"); Object obj = clazz.newInstance(); Method loginMethod = clazz.getDeclaredMethod("login", String.class, String.class); Object retValue = loginMethod.invoke(obj, "admin", "admin123"); System.out.println(retValue); } }
执行结果:
那如果调用既没有参数,又没有返回值的logout方法,应该怎么做?
package com.powernode.reflect; import java.lang.reflect.Method; /** * @author 动力节点 * @version 1.0 * @className ReflectTest03 * @since 1.0 **/ public class ReflectTest03 { public static void main(String[] args) throws Exception{ Class clazz = Class.forName("com.powernode.reflect.SystemService"); Object obj = clazz.newInstance(); Method logoutMethod = clazz.getDeclaredMethod("logout"); logoutMethod.invoke(obj); } }
执行结果:
假设你知道属性名
假设有这样一个类:
package com.powernode.reflect; /** * @author 动力节点 * @version 1.0 * @className User * @since 1.0 **/ public class User { private String name; private int 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; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
你知道以下这几条信息:
类名是:com.powernode.reflect.User
该类中有String类型的name属性和int类型的age属性。
另外你也知道该类的设计符合javabean规范。(也就是说属性私有化,对外提供setter和getter方法)
你如何通过反射机制给User对象的name属性赋值zhangsan,给age属性赋值20岁。
package com.powernode.reflect; import java.lang.reflect.Method; /** * @author 动力节点 * @version 1.0 * @className UserTest * @since 1.0 **/ public class UserTest { public static void main(String[] args) throws Exception{ // 已知类名 String className = "com.powernode.reflect.User"; // 已知属性名 String propertyName = "age"; // 通过反射机制给User对象的age属性赋值20岁 Class<?> clazz = Class.forName(className); Object obj = clazz.newInstance(); // 创建对象 // 根据属性名获取setter方法名 String setMethodName = "set" + propertyName.toUpperCase().charAt(0) + propertyName.substring(1); // 获取Method Method setMethod = clazz.getDeclaredMethod(setMethodName, int.class); // 调用Method setMethod.invoke(obj, 20); System.out.println(obj); } }
执行结果:
给User的name属性赋值zhangsan,这个大家可以尝试自己完成哦!!!