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
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方法......
如有不妥之处,还望多多指正!