反射
概述
设计一个类,创建类的对象,正向过程
Person p = new Person();
反射是一个逆向的过程,包名.类名
反射是一种动态获取对象的一种机制,对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)
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对象,进一步就能得到某个类中组成部分