Java反射的一些使用方法
程序员文章站
2022-07-12 14:30:44
...
注:默认认为反射代码与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()); } } }