学习任务:

视频学习

认识反射成员方法API

准备环境

测试获取成员方法

测试Method

测试调用成员方法

通过Class对象的如下方法可获取一个对象的成员方法信息:

// 返回所有公共成员方法对象的数组(包括父类)
public Method[] getMethods()												
// 返回所有成员方法对象的数组(包含私有的,不包括父类)
public Method[] getDeclaredMethods()		
// 返回单个公共成员方法对象(包括父类)
public Method getMethod(String name, Class<?>... parameterTypes) 		
// 返回单个成员方法对象(可以是私有的,不包括父类)
public Method getDeclaredMethod(String name, Class<?>... parameterTypes)  

下边测试这些API方法。

本节选用“多态案例”章节的类,包括:基础学生类、普通学生类、vip学生类、课程类等。

/**
 * 
 */
package com.pbteach.javase.oop.reflect2;

/**
 * 学生信息类(基础类)
 * 
 * @author 攀博课堂
 * @version v1.0
 */
public class PbStudent {

	// 学生编号
	public long id;

	// 学生昵称
	private String nickName;
	// 邮箱
	private String email;

	// 头像
	private String pic;
	// 密码
	private String password;
	// 选课列表
	private static PbCourse[] selections;
	

	//学生选课方法
	public void selectCourse(PbCourse course) {
		System.out.println("学生选课");
	}

	//父类的默认构造方法
	public PbStudent() {
		

	}
	
	//自定义的构造方法
	public PbStudent(long id, String nickName, String email) {
		this.id = id;
		this.nickName = nickName;
		this.email = email;
	}
	//获取学生在攀博课堂的服务权限内容
	public void getService() {
		
	}
	//获取折扣,多态调用时父类中此方法不会使用
	public float getDiscount() {
		
		return 1;
	}
	private int testPrivate() {
		return 0;
	}
	//getter/setter...
	
}

/**
 * 
 */
package com.pbteach.javase.oop.reflect2;

import java.time.LocalDate;

/**
 * vip学生类
 * 
 * @author 攀博课堂
 * @version v1.0
 */
public class PbStudentVip extends PbStudent {

	// vip服务截止时间
	private LocalDate vipDeadline;
	// vip服务的购买时间
	private LocalDate vipCreateTime;
	// vip专属指导老师
	public String pbteacher;
	// vip专属群
	public String pbgroup;

	public PbStudentVip(long id, String nickName, String email) {
		super(id, nickName, email);
	}

	// 获取学生在攀博课堂的服务内容
	public void getService() {
		System.out.println("=======vip学生======");
		System.out.println("攀博课堂自学Java课程");
		System.out.println("资源下载");
		System.out.println("在线问答交流");
		System.out.println("攀博课堂Vip专属老师指导");
		System.out.println("攀博课堂Vip专属交流群");

	}
	
	//子类扩展了一个和父类完全不一样的方法
	//判断vip账户是否有效
	public boolean isValid() {
		//如果vipDeadline截止时间在当前时间之后则有效
		if(vipDeadline.isAfter(LocalDate.now())) {
			System.out.println("账户有效");
			//账户有效
			return true;
		}
		System.out.println("账户无效");
		//账户无效
		return false;
		
	}
	//获取折扣
	public float getDiscount() {
		//实际企业开发中这里可有会从数据库来获取配置的折扣信息...
		
		return 0.7f;
	}
	//getter/setter

}

下边代码测试了本类及父类的成员方法。

package com.pbteach.javase.oop.reflect3;

import java.lang.reflect.Method;
import java.time.LocalDate;


/**
 * 反射成员方法测试
 * @author 攀博课堂
 * @version v1.0
 */
public class ReflectTest {

	//获取成员方法
	public static void test1() throws Exception {
		PbStudentVip pbStudentVip = new PbStudentVip(101L, "攀博", "1759102882@qq.com");
		//获取Class对象
		Class class1 = pbStudentVip.getClass();
		//获取本类的public方法 
		Method method1 = class1.getMethod("setVipCreateTime", LocalDate.class);
		System.out.println(method1);
		
		//获取父类的public方法
		Method method2 = class1.getMethod("setNickName", String.class);
		System.out.println(method2);
		
		//获取父类的Class对象
		Class superclass = class1.getSuperclass();
		//获取父类的私有方法,没有参数设置为null
		Method method3 = superclass.getDeclaredMethod("testPrivate", null);
		System.out.println(method3);
		
	}
	public static void main(String[] args) throws Exception {
		test1();
	}
}

输出:

public void com.pbteach.javase.oop.reflect3.PbStudentVip.setVipCreateTime(java.time.LocalDate)
public void com.pbteach.javase.oop.reflect3.PbStudent.setNickName(java.lang.String)
private int com.pbteach.javase.oop.reflect3.PbStudent.testPrivate()

Method对象描述了方法的信息,包括:方法名称、参数类型、返回值类型、修饰符等。

//测试Method
	public static void test2() throws Exception {
		PbStudentVip pbStudentVip = new PbStudentVip(101L, "攀博", "1759102882@qq.com");
		//获取Class对象
		Class class1 = pbStudentVip.getClass();
		//获取本类的public方法 
		Method method1 = class1.getMethod("setVipCreateTime", LocalDate.class);
		outputMethod(method1);
	}
	private static void outputMethod(Method method) {
		//方法名
		System.out.println(method.getName());
		//返回值类型
		System.out.println(method.getReturnType());
		//参数类型
		Class<?>[] parameterTypes = method.getParameterTypes();
		System.out.println("参数类型");
		for(int i=0;i<parameterTypes.length;i++) {
			System.out.println(parameterTypes[i]);
		}
		//修饰符
		int modifiers = method.getModifiers();
		System.out.println("修饰符");
		System.out.println("public:"+Modifier.isPublic(modifiers));
		System.out.println("private:"+Modifier.isPrivate(modifiers));
		System.out.println("protected:"+Modifier.isProtected(modifiers));
		System.out.println("static:"+Modifier.isStatic(modifiers));
		
	}

输出:

setVipCreateTime
void
参数类型
class java.time.LocalDate
修饰符
public:true
private:false
protected:false
static:false

通过Class对象获得了Method对象,通过Method的invoke方法调用方法。

//在具有指定参数的 方法对象上调用此 方法对象表示的底层方法。 
Object invoke(Object obj, Object... args) 
 

第一个参数:对象

第二个参数:变长参数,为要调用方法的参数。

测试代码如下:

	//通过反射调用成员方法
	public static void test3() throws Exception {
		PbStudentVip pbStudentVip = new PbStudentVip(101L, "攀博", "1759102882@qq.com");
		//获取父类的Class对象
		Class class1 = pbStudentVip.getClass().getSuperclass();
		//获取本类的public方法 
		Method method1 = class1.getMethod("setNickName", String.class);
		Method method2 = class1.getMethod("getNickName", null);
		//调用setVipCreateTime方法
		method1.invoke(pbStudentVip, "攀博");
		//调用getVipCreateTime方法
		String nickName = (String) method2.invoke(pbStudentVip, null);
		System.out.println(nickName);
		
	}

输出:

攀博
提问-攀博课堂
我要提问 不会就问,有效沟通
关注公众号,加入微信群交流提问。 攀博课堂官方公众号
问答列表,查看本知识点所有问题