反射
概述
设计一个类,创建类的对象,正向过程
Person p = new Person(); //创建对象
反射是一个逆向的过程,包名.类名 //Class.forName("com.mysql.jdbc.Driver");
反射是一种动态获取对象的一种机制,对Java语言灵活性发货很大的作用。
作用:能够在程序运行时判断任意的一个对象所属哪个类,获取该类的属性、方法、构造方法,并且能够在任意时刻进行调用
很多框架中都要使用反射,例如:Spring、Mybatis、动态代理等都用到了反射
获取反射对象Class类对象
Daily daily = new Daily ( ) ;
Class aClass = daily. getClass ( ) ;
Class< Daily> dailyClass = Daily. class ;
Class< Integer> integerClass = Integer. class ;
Class aClass = Class. forName ( "com.wjx.dto.Daily" ) ;
通过反射创建对象
1. 调用无参构造方法
newInstance ( ) ;
2. 获取类的构造方法,然后在调用newInstance ( [ 参数] ) ,来创建对象
Constructor< Daily> c = dailyClass. getConstructor ( ) ;
System. out. println ( "c = " + c) ;
Daily daily1 = c. newInstance ( ) ;
Constructor< Daily> c2 = dailyClass. getConstructor (
String. class , Double. class , Date. class , Date. class ) ;
System. out. println ( "c2 = " + c2) ;
Daily daily2 = c2. newInstance ( "反射" , 10.0 , new Date ( ) , new Date ( ) ) ;
通过反射获取构造器方法并使用
在反射机制中,把类的成员(构造方法、成员方法、成员变量)都封装成对应的类进行表示,其中构造方法使用类Constructor表示。可通过Class类中提供方法获取构造方法
(1)返回一个构造方法
Constructor<T> getConstructor(Class<?>... parameterTypes)
获取public修饰,指定参数类型所对应的构造方法
Constructor<T> DeclaredConstructor(Class<?>... parameterTypes)
获取指定类型参数所对应的构造方法(包含私有的)
(2)返回所有的构造方法
Constructor<?> [] getConstructors()
获取所有public修饰的构造方法
Constructor<?> [] getDeclaredConstructors()
获取所有的构造方法(包含私有的)
总结:
获取构造方法步骤:
1、获取到Class对象
2、获取指定构造方法
3、通过构造方法累赘newInstance()创建对象
public T newInstance(Object ... initargs)
package com. softeem. reflect;
import com. softeem. dto. Daily;
import javax. lang. model. SourceVersion;
import java. lang. reflect. Constructor;
public class ConstructorDemo01 {
public static void main ( String[ ] args) throws Exception {
Class< ? > aClass = Class. forName ( "com.softeem.dto.Daily" ) ;
Constructor< ? > c1 = aClass. getConstructor ( ) ;
Constructor< ? > c2 = aClass. getConstructor ( Integer. class , String. class ) ;
Constructor< ? > c3 = aClass. getDeclaredConstructor ( String. class ) ;
c3. setAccessible ( true ) ;
Daily daily = ( Daily) c3. newInstance ( "JDBC" ) ;
System. out. println ( "daily = " + daily) ;
Constructor< ? > [ ] cs = aClass. getDeclaredConstructors ( ) ;
for ( int i = 0 ; i < cs. length; i++ ) {
Class< ? > [ ] parameterTypes = cs[ i] . getParameterTypes ( ) ;
for ( Class< ? > type : parameterTypes) {
System. out. println ( type) ;
}
}
}
}
通过反射获取成员变量并使用
在反射中,把类中成员变量使用Field类表示,可以通过Class对象中提供的方法获取成员变量
(1)返回一个成员变量
Field getField(String name) 返回指定的public修饰的成员变量
Field getDeclaredField(String name) 返回指定的成员变量(包含私有的)
(2)返回所有成员变量
Field[] getFields() 返回所有的public修饰的成员变量
Field[] getDeclaredFields() 返回所有的成员变量(包含私有的)
总结:
获取成员变量的步骤:
1、获取Class对象
2、获取构造方法
3、通过构造方法,创建对象
4、获取指定的成员变量(获取的是私有的,则需要setAccessible(true)方法暴力访问)
5、通过方法set/get,给指定对象的指定成员变量进行赋值和获取值
public Object get(Object obj) //获取值
public void set(Object obj,Object value) //设置值
Class< Daily> dailyClass = Daily. class ;
Daily daily = dailyClass. newInstance ( ) ;
Field[ ] fields = dailyClass. getDeclaredFields ( ) ;
for ( int i = 0 ; i < fields. length; i++ ) {
System. out. print ( Modifier. toString ( fields[ i] . getModifiers ( ) ) ) ;
System. out. print ( " " ) ;
System. out. print ( fields[ i] . getType ( ) . getSimpleName ( ) ) ;
System. out. print ( " " ) ;
System. out. print ( fields[ i] . getName ( ) ) ;
System. out. println ( ) ;
}
Field idField = dailyClass. getDeclaredField ( "id" ) ;
idField. setAccessible ( true ) ;
idField. set ( daily, 4 ) ;
System. out. println ( idField. get ( daily) ) ;
通过反射获取成员方法
在反射中,把类中的成员方法封装成了一个Method类表示,通过Class类中提供的方法来获取:
(1)获取单个指定方法
Method getMethod(String name,Class<?>... parameterTypes)
获取public修饰的成员方法
Method getDeclared(String name,Class<?>... parameterTypes)
获取任意的成员方法(包含私有的)
(2)获取所有方法
Method[] getMethods()
获取本类以及父类中所有的public修饰的成员方法
Method[] getDeclaredMethods()
获取本类中所有成员方法(包含私有的)
获取成员方法的步骤:
1、获取Class对象
2、获取构造方法
3、通过构造方法创建对象
4、获取指定的方法
5、执行找到的方法
public Object invoke(Object obj,Object... args)
//invoke方法的返回值表示执行方法的返回值结果
Class< User> userClass = User. class ;
Method[ ] methods = userClass. getMethods ( ) ;
for ( Method method : methods) {
System. out. println ( "method = " + method) ;
}
System. out. println ( "------------------------" )
Method show = userClass. getMethod ( "show" ) ;
System. out. println ( "show = " + show) ;
User user = userClass. newInstance ( ) ;
Object invoke = show. invoke ( user)
System. out. println ( "invoke = " + invoke) ;
System. out. println ( "------------获取有参无返回成员方法------------" ) ;
Method show1 = userClass. getMethod ( "show" , String. class ) ;
Object abc = show1. invoke ( user, "abc" ) ;
System. out. println ( "abc = " + abc) ;
System. out. println ( "--------------获取有参有返回成员方法-----------------" ) ;
Method show2 = userClass. getMethod ( "show" , int . class ) ;
Object invoke1 = show2. invoke ( user, 1 ) ;
System. out. println ( "invoke1 = " + invoke1) ;
反射的缺点
反射的代码比我们之前正常调用的代码要多,性能也慢,所以避免使用反射
什么时候使用反射:
如果一个功能可以不用反射来完成,那么最好不用
反射存在的意义
反射机制是很多框架的“基石”
.xml文件或者properties文件写好了一下配置,然后在Java类中解析xml文件或者properties文件中的内容,得到一个字符串,根据字符串来获取某一个类Class对象,进一步就能得到某个类中组成部分