十、回顾反射机制

10.1 分析方法四要素

我们先来看一下,不使用反射机制调用一个方法需要几个要素的参与。

有一个这样的类:

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)

10.2 获取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个。所以只需要提供方法名就行了。你学会了吗?

10.3 调用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);
    }
}

执行结果:

10.4 假设你知道属性名

假设有这样一个类:

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,这个大家可以尝试自己完成哦!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值