Java反射的用法

public class Human  {
	
	private String race;
	public String civilization;

	public String getPrice() {
		return race;
	}

	public void setPrice(String price) {
		this.race = price;
	}
	private void getCivilization() {
		//do something
	}

}

public class User extends Human {
	private String name;
	String age;
	protected String sex;
	public String address;	
	
	public User() {
		
	}
	
	public User(String name, String age, String sex, String address) {		
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.address = address;
	}
	//getter...
//setter....
	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + ", sex=" + sex + ", address=" + address + "]";
	}
	private void password(String msg) {
		System.out.println(msg+"调用了password方法......");
	}

}

1.首先介绍一下使用反射创建一个对象

利用反射创建对象,有两个步骤。

1)获取到类的类型信息

2)通过调用newInstance()方法初始化对象。

Class clazz=Class.forName("com.test.bean.User");
User user=(User) clazz.newInstance();
System.out.println(user);
输出:
User [name=null, age=0, sex=null, address=null]


而获取类的类型信息有三种:

//第一种
Class.forName("com.test.bean.User");
//第二种
Class clazz=User.class;
//第三种
User user=new user();
Class clazz=user.getClass();

2.获得类的所有的公共(public)的字段,包括父类并对字段赋值

获取权限修饰符为public类型的字段

通过使用Class对象的getFields(),获取到一个Field数组,这个数组包含了类的所有public类型属性的Field对象,包含从父类继承下来的public类型属性。

User user = new User();
		Class clazz=Class.forName("com.test.bean.User");
		Field[] fields=clazz.getFields();
		for (int i = 0; i < fields.length; i++) {			
			fields[i].set(user, "中国北京");//设置字段值
			System.out.println("字段的类型:"+fields[i].getType()+"   字段名:"+fields[i].getName());
			System.out.println("字段值"+user.getAddress());
		}
注:User类只有一个public类型的字段address,所以上面的循环体只是循环一次,只设置了address的值,设置的值与字段类型不匹配会报错。

输出:

字段的类型:class java.lang.String   字段名:address        字段值:中国北京

如果知道字段具体的名称,可以通过Field(“args”)方法精确获取public修饰权限的字段,包括从父类继承下来的public字段,获取其他修饰符的字段会报异常。

Field field=clazz.getField("address");


3.获得类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段

User user = new User();
		Class clazz=Class.forName("com.test.bean.User");
		Field[] fields=clazz.getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {	
			int mf=fields[i].getModifiers();//获取字段的权限修饰符的编号数字
			String modif=Modifier.toString(mf);//通过编号获取权限修饰符的名称
			System.out.println("权限修饰符的编号数字:"+mf+"    字段的权限修饰类型:"+modif+"    字段的类型:"+fields[i].getType()+"   字段名:"+fields[i].getName());
		}
输出:

权限修饰符的编号数字:2    字段的权限修饰类型:private    字段的类型:class java.lang.String   字段名:name
权限修饰符的编号数字:0    字段的权限修饰类型:    字段的类型:int   字段名:age
权限修饰符的编号数字:4    字段的权限修饰类型:protected    字段的类型:class java.lang.String   字段名:sex
权限修饰符的编号数字:1    字段的权限修饰类型:public    字段的类型:class java.lang.String   字段名:address


通过getDeclaredField方法,也可以获取到类中所有权限修饰符的字段,不包括父类的定义的字段,以及从父类继承下来的public的字段。

Field field=clazz.getDeclaredField("name");


4.获取类的所有的公共(public)的方法,包括父类

                 User user = new User();
		Class clazz=Class.forName("com.test.bean.User");
		Method[] method=clazz.getMethods();
		for (int i = 0; i < method.length; i++) {	
			int mf=method[i].getModifiers();//获取方法的权限修饰符的编号数字
			String modif=Modifier.toString(mf);//通过编号获取权限修饰符的名称
			System.out.println("方法权限修饰符的编号数字:"+mf+"    字方法的权限修饰类型:"
			+modif+"    方法的返回值类型:"+method[i].getReturnType()+"   方法名:"+method[i].getName());
		}

输出:
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:int   方法名:getAge
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setAge
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getSex
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setSex
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setAddress
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:toString
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getAddress
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getName
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setName
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:int   方法名:getPrice
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setPrice
方法权限修饰符的编号数字:17    字方法的权限修饰类型:public final    方法的返回值类型:void   方法名:wait
方法权限修饰符的编号数字:273    字方法的权限修饰类型:public final native    方法的返回值类型:void   方法名:wait
方法权限修饰符的编号数字:17    字方法的权限修饰类型:public final    方法的返回值类型:void   方法名:wait
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:boolean   方法名:equals
方法权限修饰符的编号数字:257    字方法的权限修饰类型:public native    方法的返回值类型:int   方法名:hashCode
方法权限修饰符的编号数字:273    字方法的权限修饰类型:public final native    方法的返回值类型:class java.lang.Class   方法名:getClass
方法权限修饰符的编号数字:273    字方法的权限修饰类型:public final native    方法的返回值类型:void   方法名:notify
方法权限修饰符的编号数字:273    字方法的权限修饰类型:public final native    方法的返回值类型:void   方法名:notifyAll

所有的对象默认继承Object,因此输出了继承Object类的public方法。

如果知道方法的具体方法名以及方法的参数类型以及参数个数,可以通过getMethod方法精确获取到public权限修饰符的方法的Method对象,包括父类的public的方法。

Method method2=clazz.getMethod("setAddress", String.class);
getMethod(string name,Class...para);//第一个参数是方法名,第二个参数是可变参数,该可变参数是方法的参数类型。


5.获得类的所有定义的方法,即包括public、private和proteced,但是不包括父类定义的方法

通过把上面的 Method[] method=clazz.getMethods();改成Method[] method=clazz.getDeclaredMethods();既调用getDeclaredMethods()方法,其他代码不变就可以获取到类的所有定义的方法。

修改后的输出:

方法权限修饰符的编号数字:2    字方法的权限修饰类型:private    方法的返回值类型:void   方法名:password
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:int   方法名:getAge
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setAge
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getSex
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setSex
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setAddress
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:toString
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getAddress
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:class java.lang.String   方法名:getName
方法权限修饰符的编号数字:1    字方法的权限修饰类型:public    方法的返回值类型:void   方法名:setName

可以通过getDeclaredMethod方法精确获取到所有权限修饰符方法的Method对象,但不包括父类的。

Method method2=clazz.getDeclaredMethod("password",String.class);//User中password方法是私有的(private)
getDeclaredMethod(string name,Class...para);//第一个参数是方法名,第二个参数是可变参数,该可变参数是方法的参数类型。

6.获取类的构造函数。

获取类的所有构造函数,使用getConstructors方法返回一个包含全部构造函数对象Constructor的数组(这里构造函数有两个,因此数组中有两个Constructor类型的元素)。

 Class class1=Class.forName("com.test.bean.User");
Constructor<?>[] constructor=class1.getConstructors();
User user1=(User) constructor[0].newInstance();//通过无参构造函数来创建对象
User user2=(User) constructor[1].newInstance("李四","19","男","中国北京");

如果知道构造函数的参数列表,可以通过getConstructor方法来精确获取对应的构造函数

getConstructor(Class...para)//该方法的参数是一个可变参数。

7.通过invoke()方法调用类中的方法

Class clazz=Class.forName("com.test.bean.User");
Method method=clazz.getDeclaredMethod("password",String.class);
method.setAccessible(true);//不做安全检查,才可以去访问私有方法
method.invoke(new User(),"李四");

输出:

李四调用了password方法......


如有不妥之处,还望多多指正!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值