注:默认认为反射代码与Worker类不在同一个包下,下面的“使用条件”才是正确的。
下面以Worker类来讲解Java反射的三种用途(创建实例,调用方法,访问属性):
Worker类如下:
class Worker{
/*两个public构造方法*/
public Worker(){
count++;
}
public Worker(String name){
super();
this.name = name;
}
/*两个private构造方法*/
private Worker(String name,int age){
super();
this.name = name;
this.age = age;
}
private Worker(int age){
super();
this.age = age;
}
/*两个private属性*/
private String name;
private int age;
/*一个public属性*/
public String parents;
/*一个private static属性*/
private static int count;
/*一个 public static属性*/
public static String address;
/*两个public方法*/
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
/*两个private方法*/
private int getAge(){
return age;
}
private void setAge(int age){
this.age = age;
}
/*两个public static方法*/
public static void printAddress(String address){
System.out.println("printAddress==="+address);
}
public static void printAddress(){
System.out.println("printAddress===default");
}
/*两个private static方法*/
private static void printlnCount(int count){
System.out.println("printCount==="+count);
}
private static void printlnCount(){
System.out.println("printCount===000");
}
@Override
public String toString(){
return "这是一个Worker实例:name="+name+",age="+age;
}
}
在使用反射时,第一步要获取,被反射类的Class对象。获取Class对象有3中方法,如下:
package test;
public class ReflectTest {
public static void main(String[] args) throws Exception{
//方法1,使用"包名.类名.class"形式获取Class对象
Class c1 = Worker.class;
System.out.println("c1==="+c1);
//方法2,使用"对象名.getClass()"形式获取Class对象
Worker w = new Worker();
Class c2 = w.getClass();
System.out.println("c2==="+c2);
//方法3,使用"Class.forName("包名.类名")"形式获取Class对象
Class c3 = Class.forName("test.Worker");
System.out.println("c3==="+c3);
}
}
第一,创建实例
package test;
import java.lang.reflect.Constructor;
public class ReflectTest {
public static void main(String[] args) throws Exception{
//提前获取Class对象
Class c = Class.forName("test.Worker");
//创建实例
//方法1,使用"Class对象名.newInstance()"创建实例
//使用条件:该方法要求Worker类必须有public类型且无参的构造方法
Worker w1 = (Worker)c.newInstance();
System.out.println("w1==="+w1);
//方法2,使用getConstructor创建实例
//方法2.1,公有、无参构造方法
//使用条件:该方法要求Worker类有一个public类型且无参的构造方法
Constructor con21 = c.getConstructor();//只能获取public类型的无参构造方法
Worker w21 = (Worker)con21.newInstance();
System.out.println("w21==="+w21);
//方法2.2,公有、有参构造方法
//使用条件:该方法要求Worker的构造方法是公有的
Constructor con22 = c.getConstructor(String.class);//根据构造方法的参数类型和顺序,传入对应的Class对象
Worker w22 = (Worker)con22.newInstance("李彦宏");//根据构造方法的参数类型和顺序,传入对应的参数
System.out.println("w22==="+w22);
//方法3,使用getDeclaredConstructor创建实例
//方法3.1,无参构造方法
Constructor con31 = c.getDeclaredConstructor();//无论是private还是public类型的无参构造方法,都可以获取
con31.setAccessible(true);//关键,如果无参构造方法是private类型的,这句必须加
Worker w31 = (Worker)con31.newInstance();
System.out.println("w31==="+w31);
//方法3.2,有参构造方法
Constructor con32 = c.getDeclaredConstructor(String.class,int.class);//根据构造方法的参数类型和顺序,传入对应的Class对象
con32.setAccessible(true);//关键,如果无参构造方法是private类型的,这句必须加
Worker w32 = (Worker)con32.newInstance("周星驰",40);//根据构造方法的参数类型和顺序,传入对应参数
System.out.println("w32==="+w32);
}
}
第二,调用方法
package test;
import java.lang.reflect.Method;
public class ReflectTest {
public static void main(String[] args) throws Exception{
//提前获取Class对象
Class c = Class.forName("test.Worker");
//调用方法
//方法1,调用静态方法
//使用条件:使用之前需要先获取该类的Class对象
//方法1.1,调用公有、无参构造方法
//使用条件:该方法必须是public static和无参的
Method m11 = c.getMethod("printAddress");
m11.invoke(c);
//方法1.2,调用公有、有参构造方法
//使用条件:该方法必须是public static和有参的
Method m12 = c.getMethod("printAddress",String.class);//根据参数名、参数类型和顺序,填入正确的参数名、参数的Class对象
m12.invoke(c, "北京");//传入该类的Class对象,和方法对应的参数
//方法1.3,调用私有、有参构造方法
//使用条件:该方法无论是public还是private类型都可以使用
Method m13 = c.getDeclaredMethod("printlnCount", int.class);
m13.setAccessible(true);//关键,如果该方法是private类型的,则这句必须加
m13.invoke(c, 100);
//方法2,调用成员方法
//使用条件:使用之前必须先创建实例
Worker w = (Worker)c.newInstance();
//方法2.1,调用公有、无参成员方法
//使用条件:该方法必须是public类型且无参的方法
Method m21 = c.getMethod("getName");
System.out.println("getName==="+m21.invoke(w));
//方法2.2,调用公有、有参成员方法
//使用条件:该方法必须是public类型且有参的方法
Method m22 = c.getMethod("setName", String.class);
m22.invoke(w, "李开复");
//方法2.3,调用私有、有参成员方法
//使用条件:该方法可以是public,也可以是private类型
Method m23 = c.getDeclaredMethod("setAge", int.class);
m23.setAccessible(true);//关键,如果该方法是private类型方法,则必须加上
m23.invoke(w,20);
//另:遍历所有public方法(包括静态方法和成员方法,--也包括--父类的方法)
Method [] ms1 = c.getMethods();
for(Method m:ms1){
System.out.println(m.getName());
}
//遍历所有方法(包括静态方法和成员方法,--不包括--父类的方法)
Method [] ms2 = c.getDeclaredMethods();
for(Method m:ms2){
System.out.println(m.getName());
}
}
}
第三访问属性
package test;
import java.lang.reflect.Field;
public class ReflectTest {
public static void main(String[] args) throws Exception{
//提前获取Class对象
Class c = Class.forName("test.Worker");
//访问属性
//方法1,访问静态属性
//使用条件:使用之前需要先获取该类的Class对象
//方法1.1,访问public static属性
//使用条件:该属性必须是public static
Field f11 = c.getField("address");
f11.set(c, "天津");
System.out.println("address==="+f11.get(c));
//方法1.2,访问private static属性
//使用条件:该属性必须是static类型,可以是public类型,也可以是private类型
Field f12 = c.getDeclaredField("count");
f12.setAccessible(true);//关键,如果该属性是private类型,则该句必须加上
f12.set(c, 100);
System.out.println("count==="+f12.get(c));
//2.访问成员属性
//使用条件:使用之前需要先获取该类的实例
Worker w = new Worker("凤姐");
System.out.println("w.getName()==="+w.getName());
//方法2.1,访问public成员属性
//使用方法:该属性必须是public成员属性
Field f21 = c.getField("parents");
f21.set(w, "如花");
System.out.println("w.parents==="+w.parents);
//方法2.2,访问private成员属性
//使用方法:该属性可以是public类型,也可以是private类型
Field f22 = c.getDeclaredField("name");
f22.setAccessible(true);//关键,如果是private类型属性,则该句必须加上
f22.set(w, "芙蓉姐姐");
System.out.println("w.getName()==="+w.getName());
//另:遍历所有的public属性
Field [] fs1 = c.getFields();
for(Field f:fs1){
System.out.println("f==="+f.getName());
}
//遍历所有的属性
Field [] fs2 = c.getDeclaredFields();
for(Field f:fs2){
System.out.println("f==="+f.getName());
}
}
}