疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java反射的一些使用方法


 

     注:默认认为反射代码与Worker类不在同一个包下,下面的“使用条件”才是正确的。下面以Worker类来讲解Java反射的三种用途(创建实例,调用方法,访问属性):

  Worker类如下:

  Java代码

  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中方法,如下:

  Java代码

  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);

  }

  }

  第一,创建实例

  Java代码

  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);

  }

  }

  第二,调用方法

  Java代码

  package test;

  Java代码

  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());

  }

  }

  }

  第三访问属性

  Java代码

  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());

  }

  }

  }