如果有人问:什么是反射?为什么需要反射,以及反射的应用?你会怎么回答?本文将向您介绍反射,了解反射的概念和基本应用。反射的原理和对源码的深入探索将在接下来的几篇文章中介绍。1、什么是反射?要理解什么是反射,我们先来看看什么是“正交”。获取Student的常用拼写方式如下:Studentstudent=newStudent();通常我们直接声明,或者在使用前通过newStudent()直接获取一个Student类。反射示例如下://这里"com.demo.Student"是要反射的类的完全限定名(包名+类名)Classclz=Class.forName("com.demo.Student")对象stu=clz.newInstance();先获取实例的Class类,再通过其Class类生成StudentInstance。上面两个方法(newStudent和clz.newInstance)在效果上是等价的,都是得到一个Student的实例。那么什么是反射呢?反射是Java中的一个重要特性。使用反射,可以在运行时动态生成对象,获取对象属性,调用对象方法。Oracle对反射的官方解释是:反射使Java代码能够发现有关加载类的字段、方法和构造函数的信息,并在安全限制范围内使用反射的字段、方法和构造函数对其底层对应项进行操作。API适合需要访问目标对象的公共成员(基于其运行时类)或给定类声明的成员的应用程序。它还允许程序抑制默认反射访问控制。反射的核心是JVM只是在运行时动态地加载一个类或者调用一个方法/访问一个属性,它不需要提前(写代码时或者编译时)知道运行对象是谁。反射的问题:这里简单提一下:反射相当于一系列的解释操作,通知JVM要做什么,其性能比直接Java代码慢很多。第二,为什么需要反思?举一个直观的例子(只是为了说明一种用法):如果我让你根据运行时输入的名字写一个打印输出,你会写出类似下面的代码:publicvoidsayHello(Stringname){//你不'在运行前就知道名字是什么,只有在运行时才会确认并打印出名字。System.out.println("hello,"+name);}那么类似的,你可能不知道要用什么类,运行时是知道的。比如在加载数据库驱动的时候,直接new出具体的驱动类就可以了,但是如果换了数据库,是不是需要修改源码,重新打包更新?新的com.mysql.jdbc.Driver();那你可能会说,我再写几个ifelse就可以了,类似下面这样:if(xxx=="mysql"){newcom.mysql.jdbc.Driver();elseif(xxx=="redis"){newcom.redis.jdbc.Driver();elseif(...){}这样做的问题是编译时所有的jdbc连接都必须组装库,不管是使用还是不会,会加载到内存中。如果数据库类型过多,会造成巨大的浪费。那么这种情况可以通过反射来解决,在运行时动态加载对应的类。你也可以在配置文件中指定使用哪个数据库类,你可以使用这个程序来连接不同的数据库。//反射方式动态加载类Class.forName("com.mysql.jdbc.Driver");3.反射的基本使用下面介绍通过反射可以做什么:1)获取Class对象//1使用Class类forName静态方法Class.forName(driver);//2直接获取classClass>ofanobjectcl=int.class;//3调用对象的getClass()方法StringBuilderstr=newStringBuilder("123");Class>klass=str.getClass();2)判断是否是某个类的实例publicstaticvoiddisplayObjectClass(Objecto){if(oinstanceofVector)System.out.println("该对象是java.util.Vector类实例");elseif(oinstanceofArrayList)System.out.println("该对象是java.util.ArrayList类的一个实例");elseSystem.out.println("Theobjectis"+o.getClass()+"instanceoftheclass");}3)创建实例Class>c=String.class;对象str=c.newInstance();4)获取方法getDeclaredMethods()方法返回类或接口的所有声明方法,包括public、protected、默认(包)访问和私有方法,但不包括继承方法。getMethods()方法返回类的所有公共方法,包括其继承类的公共方法。getMethod()方法返回一个具体的方法,其中第一个参数是方法名,后面的参数是方法参数对应的Class的对象。公共类ReflectDemo{publicstaticvoidmain(String[]args)throwsIllegalAccessException,InstantiationException,NoSuchMethodException,InvocationTargetException{Class>c=MyClass.class;方法[]方法=c.getMethods();方法[]declaredMethods=c.getDeclaredMethods();方法method=c.getMethod("add",int.class,int.class);System.out.println("getMethods获取的方法:");for(Methodm:methods)System.out.println(m);System.out.println("getDeclaredMethods获取的方法:");for(Methodm:declaredMethods)System.out.println(m);}}classMyClass{publicintadd(inta,intb){returna+b;}publicintsub(inta,intb){returna-b;}}//输出/*getMethods获取的方法:publicintcom.shuofxz.basic.ReflectDemo$MyClass.add(int,int)publicintcom.shuofxz.basic.ReflectDemo$MyClass.sub(int,int)publicfinal无效的java.lang.Object.wait(long,int)抛出java.lang.InterruptedException.InterruptedExceptionpublicbooleanjava.lang.Object.equals(java.lang.Object)publicjava.lang.Stringjava.lang.Object.toString()publicnativeintjava.lang.Object.hashCode()publicfinalnativejava.lang。Classjava.lang.Object.getClass()publicfinalnativevoidjava.lang.Object.notify()publicfinalnativevoidjava.lang.Object.notifyAll()getDeclaredMethods获取方法:publicintcom.shuofxz.basic.ReflectDemo$MyClass.add(int,int)publicintcom.shuofxz.basic.ReflectDemo$MyClass.sub(int,int)*/5)调用方法当我们从类中获取一个方法时,我们可以使用invoke()来调用它方法公共类ReflectDemo{publicstaticvoidmain(String[]args)throwsIllegalAccessException,InstantiationException,NoSuchMethodException,InvocationTargetException{Class>mc=MyClass.class;对象obj=mc.newInstance();//获取方法类添加方法Methodmethod=mc.getMethod("add",int.class,int.class);//调用method对应的方法=>add(1,4)Objectresult=method.invoke(obj,1,4);系统.out.println(结果);}}6)获取类的构造函数和成员变量(字段)信息通过Class类的getConstructor方法获取Constructor类的实例getFiled:访问公共成员变量getDeclaredField:所有声明的成员变量,但无法获取成员变量其父类IV。小结本文初步介绍了反射机制。让大家明白什么是反射,为什么会有反射的功能,以及一些基本的使用方法。后续文章将进一步阐述反射的机制和原理。
