Java反射基础
一.Java中反射的概念
在Java中的反射机制,被称为Reflection。它允许运行中的Java程序对自身进行检查,并能直接操作程序的内部属性或方法。Reflection机制允许程序在正在执行的过程中,利用Reflection APIs取得任何已知名称的类的package、 type parameters、 superclass、implemented interfaces、Inner class、outer class、fields、construtors、methods、modifier等,并可以在执行的过程中,动态的生成instance、变更fields内容或调用methods。总之一句话,Java反射就是动态的使用类。
二.实例化Class类,有三种方法:
1.如果直接有一个类的对象 比如:
Person p = new Person();
Class clazz = p.getClass();
2.如果知道类名,比如
Class clazz = Person.class;
3.如果只带全类名的话,比如:
String className = "com.java.Person";
Class clazz = Class.forName(className);
一般来说,这种方法用来求类名不确定的类的镜象
三.代码示例:
要被反射的类的代码ModelClass.java
1 package test.java.reflection; 2 3 public class ModelClass { 4 private int id; 5 private String name; 6 7 public ModelClass(){ 8 9 } 10 11 public ModelClass(int id,String name){ 12 this.id = id; 13 this.name = name; 14 15 } 16 17 public ModelClass(int id){ 18 this(id,"xiaohu"); 19 } 20 21 public ModelClass(String name){ 22 this(18,name); 23 } 24 25 public int getId() { 26 return id; 27 } 28 29 public void setId(int id) { 30 this.id = id; 31 } 32 33 public String getName() { 34 return name; 35 } 36 37 public void setName(String name) { 38 this.name = name; 39 } 40 41 42 43 }
1.根据类名获取类中所有的构造方法,以及参数类型,并打印
Class clazz = Class.forName(className);
claszz.getConstrctors();//返回类型是Constructor数组,此方法不能获取私有的(private)类型的构造函数
clazz.getDeclaredConstructors();//返回类型是Constructor数组,获取类中所有的构造函数,包括private类型的。
clazz.getConstructor(Class... parameterTypes);//获取特定参数的构造函数,参数的类型是Class类型的。此方法不能获取私有的构造函数
clazz.getDeclaredConstructor(Class... parameterTypes);//获取特定参数的构造函数,参数的类型是Class类型的。此方法能获取所有的构造函数,包括私有(private)的
Constructor类有个方法 getModifiers()返回值是int型的,int值对应一个修饰符。用Modifier.toString(int ) 可以获取到那个int值所对应的修饰符的Sring类型。
具体代码如下:
1 public static void getReflectionConstructors(String className) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ 2 System.out.println("获取 "+className+" 类中的所有构造方法"); 3 //获取类的class镜像 4 Class clazz = Class.forName(className); 5 //获取构造器类的额的数组 6 Constructor[] constructors = clazz.getDeclaredConstructors(); 7 for(int i=0;i<constructors.length;i++){ 8 int modi = constructors[i].getModifiers(); 9 String modifier = Modifier.toString(modi); 10 System.out.print(modifier +" " +className+" ("); 11 Class[] paramters = constructors[i].getParameterTypes(); 12 for(int j=0;j<paramters.length;j++){ 13 if(j!=0) System.out.print(","); 14 System.out.print(Modifier. toString(paramters[j].getModifiers())+" "+paramters[j].getName()); 15 } 16 System.out.println(")"); 17 } 18 }
结果截图如下:
2.获取类中的所有属性的数据类型和修饰符,并打印
1 public static void getReflectionFelds(String className) throws ClassNotFoundException{ 2 System.out.println("获取 "+className+" 类中的所有属性"); 3 //获取类的镜象 4 Class clazz = Class.forName(className); 5 Field[] fields = clazz.getDeclaredFields(); 6 for(int i=0;i<fields.length;i++){ 7 System.out.println(Modifier.toString(fields[i].getModifiers())+" "+fields[i].getName()); 8 } 9 }
结果如下截图:
3.获取类中所有方法,并打印
1 public static void getReflectionMethods(String className) throws ClassNotFoundException{ 2 System.out.println("获取 "+className+" 类中的所有普通方法"); 3 //获取类的镜像 4 Class clazz = Class.forName(className); 5 //获取所有方法对应的类的数组 6 Method[] methods =clazz.getDeclaredMethods(); 7 //遍历所有方法 8 for(int i=0;i<methods.length;i++){ 9 //获取所有方法的修饰符 ,返回值类型,方法名 10 System.out.print(Modifier.toString(methods[i].getModifiers())+ 11 " "+methods[i].getReturnType().getName()+ 12 " "+methods[i].getName()+"("); 13 //获取所有参数的类型对应的镜像 14 Class[] parametersType = methods[i].getParameterTypes(); 15 for(int j = 0;j<parametersType.length;j++){ 16 System.out.print(parametersType[j].getName()); 17 if(parametersType.length>j+1) 18 System.out.print(","); 19 } 20 System.out.println(")"); 21 } 22 23 }
结果如下截图:
4.根据类名创建实例,并根据类属性的名称,选择要调用的方法获取属性值
代码如下:
1 public static void getReflectionInstatnce(String className) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{ 2 System.out.println("根据类名 "+className+" 创建实例并根据类属性的名称选择要调用的方法获取属性值"); 3 Class<?> clazz = Class.forName(className); 4 Constructor<?> constructor = clazz.getDeclaredConstructor(int.class,String.class); 5 ModelClass model = (ModelClass) constructor.newInstance(18,"xiaohu"); 6 //System.out.println("id = "+model.getId()+" name = "+model.getName()); 7 Field[] fields = clazz.getDeclaredFields(); 8 for(int i=0;i<fields.length;i++){ 9 //获取属性名的第一个字母,并转换为大写 10 String leftFirst = fields[i].getName().substring(0, 1).toUpperCase(); 11 //获取属性名第一个字母以后的其他字符 12 String right = fields[i].getName().substring(1); 13 //拼接出get方法的名字 14 String methodName = "get"+leftFirst+right; 15 Method method = clazz.getDeclaredMethod(methodName); 16 System.out.println(fields[i].getName()+" = "+method.invoke(model)); 17 18 } 19 }
结果如下:
据类名 test.java.reflection.ModelClass 创建实例并根据类属性的名称选择要调用的方法获取属性值
id = 18
name = xiaohu