Java反射机制及API使用

原文地址
反射简单来说,就是动态加载对象,并对对象进行剖析。在Java中的反射机制是指在运行状态中,对于任意一个类,都能够知道并获取这个类的所有属性和方法。
Java反射机制的作用:

  • 在运行时判断任意一个对象所属的类。
  • 在运行时判断任意一个类所具有的成员变量和方法。
  • 在运行时任意调用一个对象的方法
  • 在运行时构造任意一个类的对象
反射机制的优缺点是什么? 反射机制的优点就是可以实现动态创建对象和编译,体现出很大的灵活性。
它的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它
满足我们的要求。这类操作总是慢于只直接执行相同的操作。
获取Class对象的三种方式
package com.gyl; public class Student { public int no; public String sex; private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; }/* * 构造方法 */Student(String str){ System.out.println("(默认)的构造方法 s = " + str); }//无参构造方法 public Student(){ System.out.println("调用了公有、无参构造方法执行了。。。"); }//有一个参数的构造方法 protected Student(char name){ System.out.println("姓名:" + name); }//有多个参数的构造方法 public Student(String name ,int age){ System.out.println("姓名:"+name+"年龄:"+ age); //这的执行效率有问题,以后解决。 }//私有构造方法 private Student(int age){ System.out.println("私有的构造方法年龄:"+ age); }}

package com.gyl; import java.lang.reflect.Constructor; public class Main { public static void main(String[] args) throws ClassNotFoundException { Student student = new Student(); /* * JAVA反射--获取Class对象的三种方式 */// 通过对象名.getClass()方法获取 Class stuClass = student.getClass(); System.out.println("stuClass is "+stuClass.getName()); // 通过类名.class方式获得 Class stuClass1 = Student.class; System.out.println("stuClass1 is "+stuClass1.getName()); System.out.println(stuClass == stuClass1); // 通过Class.forName()方法获得 Class stuClass2 = Class.forName("com.gyl.Student"); System.out.println("stuClass2 is "+stuClass2); System.out.println(stuClass1 == stuClass2); } }Output: stuClass is com.gyl.Student stuClass1 is com.gyl.Student true stuClass2 is class com.gyl.Student true

在运行期间,一个类,只有一个Class对象产生。三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都选第三种,一个字符串可以传入也可写在配置文件中等多种方法。
反射API 获取构造方法
// 返回指定参数类型 public的构造器。 Constructor getConstructor(类... parameterTypes) // 返回指定参数类型的构造器(public, protected, private)。 Constructor getDeclaredConstructor(类... parameterTypes) // 返回所有的public类型的构造器 Constructor[] getConstructors() // 返回所有的构造器 Constructor[] getDeclaredConstructors()

package com.gyl; import java.lang.reflect.Constructor; public class Main { public static void main(String[] args) throws ClassNotFoundException {// 通过Class.forName()方法获得Class对象 Class stuClass = Class.forName("com.gyl.Student"); System.out.println("************返回所有public构造方法************"); Constructor[] constructors = stuClass.getConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } /* * Output: * ************返回所有public构造方法************ *public com.gyl.Student() *public com.gyl.Student(java.lang.String,int) */System.out.println("************所有的构造方法(包括:私有、受保护、默认、公有)***************"); Constructor[] constructors2 = stuClass.getDeclaredConstructors(); for (Constructor constructor : constructors2) { System.out.println(constructor); } /* * Output: * ************所有的构造方法(包括:私有、受保护、默认、公有)*************** *private com.gyl.Student(int) *public com.gyl.Student() *protected com.gyl.Student(char) *public com.gyl.Student(java.lang.String,int) *com.gyl.Student(java.lang.String) */Constructor constructor; System.out.println("************返回指定类型的 public构造器************"); try { constructor = stuClass.getConstructor(String.class, int.class); System.out.println(constructor); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * ************返回指定类型的 public构造器************ * public com.gyl.Student(java.lang.String,int) * * 如果指定参数的构造器是非public类型的 则抛出java.lang.NoSuchMethodException异常 */System.out.println("************返回指定类型的构造器************"); try { constructor = stuClass.getDeclaredConstructor(int.class); System.out.println(constructor); // char.class } catch (NoSuchMethodException e) {// String.class, int.class e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * ************返回指定类型的构造器************ * public com.gyl.Student(java.lang.String,int) * protected com.gyl.Student(char) * private com.gyl.Student(int) */ } }

获取变量
// 根据变量名获得对应的变量,访问权限不限; Field getDeclaredField(String name) // 获得类中所有属性变量 Field[] getDeclaredFields()// 根据变量名获取对应public类型的属性变量 Field getField(String name) // 获取类中所有public类型的属性变量 Field[] getFields()

package com.gyl; import java.lang.reflect.Field; public class Main { public static void main(String[] args) throws ClassNotFoundException {// 通过Class.forName()方法获得Class对象 Class stuClass = Class.forName("com.gyl.Student"); try { Field field1 = stuClass.getField("sex"); System.out.println(field1); Field field = stuClass.getDeclaredField("name"); System.out.println(field); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } /* * Output: * public java.lang.String com.gyl.Student.sex * private java.lang.String com.gyl.Student.name * 如果使用getField方法指定了一个非public类型的属性,则抛出java.lang.NoSuchFieldException异常 */Field[] fields1 = stuClass.getFields(); Field[] fields = stuClass.getDeclaredFields(); System.out.println("************返回所有public属性************"); for (Field field : fields1) { System.out.println(field); } /* * Output: * ************返回所有public属性************ *public int com.gyl.Student.no *public java.lang.String com.gyl.Student.sex */System.out.println("************返回所有属性************"); for (Field field : fields) { System.out.println(field); } /* * Output: * ************返回所有属性************ *public int com.gyl.Student.no *public java.lang.String com.gyl.Student.sex *private java.lang.String com.gyl.Student.name *private int com.gyl.Student.age */ } }

获取方法
// 获取“名称是name,参数是parameterTypes”的public的函数(包括从基类继承的、从接口实现的所有public函数) public MethodgetMethod(String name, Class[] parameterTypes)// 获取全部的public的函数(包括从基类继承的、从接口实现的所有public函数) public Method[]getMethods()// 获取“名称是name,参数是parameterTypes”,并且是类自身声明的函数,包含public、protected和private方法。 public MethodgetDeclaredMethod(String name, Class[] parameterTypes)// 获取全部的类自身声明的函数,包含public、protected和private方法。 public Method[]getDeclaredMethods()// 如果这个类是“其它类中某个方法的内部类”,调用getEnclosingMethod()就是这个类所在的方法;若不存在,返回null。 public MethodgetEnclosingMethod()

package com.gyl; import java.lang.reflect.Method; public class Main { public static void main(String[] args) throws ClassNotFoundException {// 通过Class.forName()方法获得Class对象 Class stuClass = Class.forName("com.gyl.Student"); Method method; try { //method = stuClass.getMethod("getName"); method = stuClass.getDeclaredMethod("getAge"); System.out.println(method); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); }System.out.println("*********输出所有方法********"); Method[] methods = stuClass.getDeclaredMethods(); for (Method method2 : methods) { System.out.println(method2); } /* * Output: * public int com.gyl.Student.getAge() **********输出所有方法******** *public java.lang.String com.gyl.Student.getName() *public void com.gyl.Student.setName(java.lang.String) *void com.gyl.Student.print(java.lang.String) *public int com.gyl.Student.getAge() *public void com.gyl.Student.setAge(int) */ } }

通过反射越过泛型检查 泛型用在编译期,编译过后泛型擦除(消失掉)。所以是可以通过反射越过泛型检查的
import java.lang.reflect.Method; import java.util.ArrayList; /* * 通过反射越过泛型检查 * * 例如:有一个String泛型的集合,怎样能向这个集合中添加一个Integer类型的值? */ public class Demo { public static void main(String[] args) throws Exception{ ArrayList strList = new ArrayList<>(); strList.add("aaa"); strList.add("bbb"); //strList.add(100); //获取ArrayList的Class对象,反向的调用add()方法,添加数据 Class listClass = strList.getClass(); //得到 strList 对象的字节码 对象 //获取add()方法 Method m = listClass.getMethod("add", Object.class); //调用add()方法 m.invoke(strList, 100); //遍历集合 for(Object obj : strList){ System.out.println(obj); System.out.println(obj.getClass()); } /* *Output: * aaa * class java.lang.String * bbb * class java.lang.String * 100 * class java.lang.Integer */ } }

【Java反射机制及API使用】其他方法请参考Java jdk,本文参考自Java jdk1.8

    推荐阅读