Java反射的用法

来源:互联网 发布:吃鸡网络延迟 编辑:程序博客网 时间:2024/06/13 05:48
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....@Overridepublic 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方法......


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

原创粉丝点击