Java反射学习笔记

前言

先说说反射的作用。我们都知道处于安全、维护方便等因素的考虑,java中定义了4中访问权限,分别是:private(仅限本类)、默认无关键字(本包内所有类,包含本包内的子类)、protected(本包、其他包的子类)、public(所有类)。然后因为某些特殊的需要,需要访问某些原本不可见的方法(或者字段),比如访问某个Person类内部的某个private方法,则一般的方法是不行的,这个时候反射的作用就体现出来了。

正题:

在Java中的各种操作,无非就是对类、字段、方法这三类操作,因为在反射中,也定义了三个类Class、Field、Method来分别对这三个进行处理(从英文的字面也可以看出来)。

如果我们要获得某个类的字段(或方法),则步骤一般如下:

1、获取该类的“一个Class实例”,比如

Class<Person> mPersonClass=Person.class;

当然,通过Person的实例来获取也可以的,比如有一个mPerson的实例,则这样也可以

Class<Person> mPersonClass=mPerson.getClass();

2、用class实例来获取字段(或方法),比如

Method method=mPersonClass.getDeclaredMethod("setAge",int.class);
这个方法如果成功的话,会得到一个Method实例,如果不成功,则会报错,常见的报错有NoSuchMethodException。

注意:一般对于Method而言,常用的获取方式有getMethod()和getDeclaredMethod()两种,但是更建议用后者,因为前者只当需要反射的方法是public时才有效,如果对于private方法也使用getMethod(),则会报NoSuchMethodException错误!!!getDeclaredMethod()对于private也一样使用。类似的的,对于Field有getField()和getDeclaredField()两种,推荐使用后者,原因是一样的。

getDeclaredMethod()这个方法中有2部分参数,第一部分是方法名,第2部分是声明参数类型,比如在Person类中有private boolean setInfo(String name,int age)方法,则按如下形式,返回值类型不需要加入第2部分的参数中

Method method=mPerson.getDeclaredMethod("setInfo",String.class,int.class)

3、设置可访问,这一点对于private的字段或方法尤其重要,不然一样会报错

method.setAccessible(true);

4、进行方法或字段的操作,对于方法调用,使用method.invoke();需要传入2部分参数:1、调用的对象,2、参数列表(如果方法不需要参数,则不需要;如果需要,则按顺序对应写入,这个和getDeclaredMethod()声明的应该对应)

boolean result=method.invoke(Person.class.newInstance(),20);
//这里讲年龄设置为20,第一部分的参数也可以用你自己获取到的对象

对于field,则有get()和set()方法,原理类似,需传入:对象+参数列表

11/10注:第一个参数是调用对象,如果是反射的是静态方法,则可传入null或者是对象

例子:

现在我有个Person类,通过反射调用其中的方法:

Person.java

package edu.hust.cs;

public class Person {

	/**年龄*/
	private int age=0;
	
	/**姓名*/
	private String name=null;
	
	/**下面的语句块,在创建对象时会调用。
	 * 顺序为:成员变量>下面的语句块>构造器
	 * */
	{
		System.out.println("初始化时,Name:"+name+",Age:"+age);
	}
	
	private boolean setPersonInfo(String _name)
	{
		name=_name;
		System.out.println("只设置姓名时,Name:"+name+",Age:"+age);
		return true;
	}
	
	private boolean setPersonInfo(String _name,int _age)
	{
		name=_name;
		age=_age;
		System.out.println("设置姓名和年龄时,Name:"+name+",Age:"+age);
		return false;
	}
}

测试类Test.java

package edu.hust.cs;

import java.lang.reflect.Method;

public class Test {

	public static void main(String[] args) 
	{
		try{
			//获取一个实例
			//当然也可以直接new Person();
			Person person=Person.class.newInstance();
			//反射"setPersonInfo(String _name)"方法
			Method method=person.getClass().
					getDeclaredMethod("setPersonInfo",String.class);
			//因为原方法为private,所以设置可访问,这一条语句是必须的!
			method.setAccessible(true);
			//调用该方法,并获取返回结果
			boolean result=(boolean) method.invoke(person,"张三");
			System.out.println(result);
			
			//反射"setPersonInfo(String _name,int _age)"方法
			Method method2=person.getClass().
					getDeclaredMethod("setPersonInfo",String.class,int.class);
			method2.setAccessible(true);
			boolean result2=(boolean) method2.invoke(person,"张三",23);
			System.out.println(result2);
			
		}catch(Exception e){
			e.printStackTrace();
		}
		System.exit(0);
	}
}

输出结果如下:

初始化时,Name:null,Age:0
只设置姓名时,Name:张三,Age:0
true
设置姓名和年龄时,Name:张三,Age:23
false


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值