反射是什么
反射的作用用一句简单的话来讲就是可以对代码进行操作的代码,这个特性经常在被用于创建JavaBean中,通常造轮子的人会用到这个特性,而应用程序员用到这个特性的场景则较少。
能够分析类能力的程序就叫做反射,简单来说就是可以对代码进行操作的代码。反射机制的功能极为强大,可以用来:
- 在运行时分析类的能力
- 在运行时查看对象
- 实现通用的数组操作代码
- 利用Method对象来实现方法
从获取Class类开始
在程序运行期间,Java运行时系统始终为所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。这个类的获取方式有以下三种:
使用Object类中的
getClass()
方法来返回一个Class类的实例
:User user;Class userClass = user.getClass();
我们可以使用Class类的
getName()
方法来获取包含包名在内的类名
。同样的,在已知这个名字的情况下,我们可以使用静态方法forName()获得类名对应的Class对象
:
Random generator = new Random();Class randomClass = generator.getClass();//className = "java.util.Random"String className = randomClass.getName();//第二种方式获取Class newRandomClass = Class.forName(className);
- 获得Class类对象的第三种方法很简单,如果T是任意的Java类型(或者void关键字),T.class将代表匹配的类对象。例如:
Class randomClass = Random.class;Class intClass = int.class;Class doubleClass = Double[].class;
如果我们想要创建一个类的实例,可以使用newInstance()
方法来动态创建:
String s = "java.util.Random";Object m = Class.forName(s).newInstance();
构造函数的反射
获得构造函数的方法
//根据指定参数获得public构造器 Constructor getConstructor(Class[] params); //获得public的所有构造器 Constructor[] getConstructors(); //根据指定参数获得public和非public的构造器 Constructor getDeclaredConstructor(Class[] params); //获得public的所有构造器 Constructor[] getDeclaredConstructors();
看这些方法如何使用,先来个Student类供我们反射使用
public class Student { private static String TAG = Student.class.getSimpleName(); public int age; private String name; public Student() { age = 20; name = "小明"; } public Student(int age, String name) { Log.e(TAG, "Student: " + "age " + age + " name " + name); } public void StudentA() { Log.e(TAG, "StudentA: "); } public void StudentA(int age) { Log.e(TAG, "StudentA: " + "age " + age); } public void StudentA(int age, String name) { Log.e(TAG, "StudentA: " + "age " + age + " name " + name); }}
利用反射分析类的能力
在java.lang.reflect包(反射库)中有三各类Field
,Method
和Constructor
分别用于描述类的域,方法和构造器。这三个类都有一个叫做getName()
的方法,用于返回项目的名称。Filed类有一个getType()
方法,用于返回描述域所属类型的Class对象。Method和Constructor类有能够报告参数类型的方法,Method类还有一个可以报告返回类型的方法。
这三个类还有一个叫做getModifiers()
的方法,它将返回一个整型数值,用不同的位开关描述public和static这样的修饰符使用情况。另外,还可以利用java.lang.reflect包中的Modifier类的静态方法分析getModifiers()
返回的整型数值。例如,可以使用Modifier类中的isPublic()
,isPrivate()
或isFinal()
判断方法或构造器是否是public,private或final。我们需要做的全部工作就是调用Modifier类的相应方法,并对返回的整数数值进行分析,另外,还可以利用Modifier.toString()
方法将修饰符打印出来。
Class类中的getFields()
,getMethods()
和getConstructors()
方法将分别返回类提供的public域、方法和构造器数组,其中包括超类的公有成员。Class类的getDeclareFieds()
,getDeclareMethods()
和getDeclareConstructors()
方法将分别返回类中声明的全部域、方法和构造器,其中包括私有和受保护成员,但不包括超类的成员。
下面我们来编写一个程序可以做到输入类名,然后打印出这个类的全部信息的作用:
package com.reflect.test;import com.sun.org.apache.xpath.internal.operations.Mod;import java.io.File;import java.lang.reflect.Constructor;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.util.Scanner;public class ReflectionTest { public static void main(String[] args) { String name; if(args.length > 0){ name = args[0]; }else{ Scanner in = new Scanner(System.in); System.out.println("请输入类名:"); name = in.next(); } try{ Class c1 = Class.forName(name); Class superclass = c1.getSuperclass(); String modifiers = Modifier.toString(c1.getModifiers()); if(modifiers.length() > 0){ System.out.println(modifiers + " "); } System.out.println("class"+name); if(superclass != null && superclass != Object.class){ System.out.println("extends"+superclass.getName()); } System.out.println("\n{\n"); printConstructors(c1); System.out.println(); printMethods(c1); System.out.println(); printFields(c1); System.out.println("}"); }catch (ClassNotFoundException e){ e.printStackTrace(); } System.exit(0); } private static void printFields(Class c1) { Field[] fields = c1.getDeclaredFields(); for(Field field : fields){ Class type = field.getType(); String name = field.getName(); System.out.println(" "); String modifiers = Modifier.toString(field.getModifiers()); if(modifiers.length() > 0){ System.out.println(modifiers + " "); } System.out.println(type.getName() + " " + name + ";"); } } private static void printMethods(Class c1) { Method[] methods = c1.getDeclaredMethods(); for(Method method : methods){ Class returnType = method.getReturnType(); String name = method.getName(); System.out.println(" "); String modifiers = Modifier.toString(method.getModifiers()); if(modifiers.length() > 0){ System.out.println(modifiers + " "); } System.out.println(returnType.getName()+" "+name+"("); Class[] paramTypes = method.getParameterTypes(); for(int j = 0; j < paramTypes.length; j++){ if(j > 0){ System.out.println(","); } System.out.println(paramTypes[j].getName()); } System.out.println(");"); } } private static void printConstructors(Class c1) { Constructor[] constructors = c1.getDeclaredConstructors(); for(Constructor constructor : constructors){ String name = constructor.getName(); System.out.println(" "); String modifiers = Modifier.toString(constructor.getModifiers()); if(modifiers.length() > 0){ System.out.println(modifiers + " "); } System.out.println(name + "("); Class[] paramTypes = constructor.getParameterTypes(); for(int j = 0; j < paramTypes.length; j++){ if(j > 0){ System.out.println(","); } System.out.println(paramTypes[j].getName()); } System.out.println(");"); } }}
输入java.long.Double
回显:
请输入类名:java.lang.Doublepublic final Disconnected from the target VM, address: '127.0.0.1:51190', transport: 'socket'classjava.lang.Doubleextendsjava.lang.Number{ public java.lang.Double(double); public java.lang.Double(java.lang.String); public boolean equals(java.lang.Object); public static java.lang.String toString(double); public java.lang.String toString(); public int hashCode(); public static int hashCode(double); public static double min(double,double); public static double max(double,double); public static native long doubleToRawLongBits(double); public static long doubleToLongBits(double); public static native double longBitsToDouble(long); public volatile int compareTo(java.lang.Object); public int compareTo(java.lang.Double); public byte byteValue(); public short shortValue(); public int intValue(); public long longValue(); public float floatValue(); public double doubleValue(); public static java.lang.Double valueOf(java.lang.String); public static java.lang.Double valueOf(double); public static java.lang.String toHexString(double); public static int compare(double,double); public static boolean isNaN(double); public boolean isNaN(); public static boolean isFinite(double); public static boolean isInfinite(double); public boolean isInfinite(); public static double sum(double,double); public static double parseDouble(java.lang.String); public static final double POSITIVE_INFINITY; public static final double NEGATIVE_INFINITY; public static final double NaN; public static final double MAX_VALUE; public static final double MIN_NORMAL; public static final double MIN_VALUE; public static final int MAX_EXPONENT; public static final int MIN_EXPONENT; public static final int SIZE; public static final int BYTES; public static final java.lang.Class TYPE; private final double value; private static final long serialVersionUID;}Process finished with exit code 0
不积跬步无以至千里
思维导图
扩展阅读: