反射
一、什么是反射
反射就是对于任意一个类,都能知道这个类的所有属性和方法;对于任意一个对象都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称之为JAVA语言的反射机制。
我们创建的每一个类都是对象,类本身是Class类的实例对象,这个实例对象称之为类对象,也就是Class对象
二、Class对象的特点
1、Class类的实例对象表示正在运行的java应用程序中的类和接口。jvm中有很多的实例,每一个类都有唯一的Class对象
2、Class类没有公共的构造方法。Class类是在加载类时由Java 虚拟机自动构造的
3、Class 对象用于提供类本身的信息,比如有几种构造方法, 有多少属性,有哪些普通方法
三、获取类对象
Class.forName()(常用)
Hero.class
new Hero().getClass()
一个类只会有一个类对,以上三种取出来的类对象都是一个样的
四、利用反射机制创建对象
1.获取类对象 Class class = Class.forName("pojo.Hero");
2.获取构造器对象 Constructor con = clazz.getConstructor(形参.class);
3 获取对象 Hero hero =con.newInstance(实参);
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Class clazz = Class.forName("com.zgq.entity.dto.Employee");
Constructor constructor = clazz.getConstructor(null);
Constructor[] constructors = clazz.getConstructors();
Constructor[] declaredAnnotations = clazz.getDeclaredConstructors();
Constructor constructor1 = clazz.getConstructor(String.class,Integer.class,Double.class);
System.out.println(constructor1.toString());
System.out.println(declaredAnnotations.toString());
System.out.println("所有"+constructors.toString());
System.out.println(constructor.toString());
Employee e = (Employee) constructor.newInstance();
e.setAge(20);
e.setUserName("tom");
e.setSalary(30000D);
Employee employee = (Employee) constructor1.newInstance("jack",10,1000D);
System.out.println(e);
System.out.println(employee);
}
Run:
public com.zgq.entity.dto.Employee(java.lang.String,java.lang.Integer,java.lang.Double)
[Ljava.lang.reflect.Constructor;@38af3868
所有[Ljava.lang.reflect.Constructor;@77459877
public com.zgq.entity.dto.Employee()
Employee{userName='tom', age=20, salary=30000.0}
Employee{userName='jack', age=10, salary=1000.0}
五、获取成员变量、方法并使用
基本步骤:
1、获取类对象h
2、获取属性(方法)Field f1 = h.getDeclaredField("属性名")/h.getDeclaredMethods(String name ,Class<?>… parameterTypes)
3、修改属性 f1.set(h,实参),注意这里的h是对象,不是类对象/调用方法method.invoke
获取HeroPlus类的对象 h
获取成员方法:
public Method getMethod(String name ,Class<?>… parameterTypes):获取"公有方法";(包含了父类的方法也包含Object类)
public Method getDeclaredMethods(String name ,Class<?>… parameterTypes) :获取成员方法,包括私有的(不包括继承的)
参数解释:
name : 方法名;
Class … : 形参的Class类型对象
调用方法
Method --> public Object invoke(Object obj,Object… args):
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, InstantiationException {
Class<?> aClass = Class.forName("com.zgq.entity.dto.Employee");
Method login = aClass.getMethod("sayHello", Integer.class);
Method say = aClass.getDeclaredMethod("say", String.class);
login.invoke(123);
Field userName = aClass.getDeclaredField("userName");
Field hhh = aClass.getField("hhh");
userName.setAccessible(true);
userName.set("wjj",String.class);
System.out.println(aClass.getMethod("login", String.class, String.class).invoke("jack","1314520wjj"));
Method main = aClass.getMethod("main", String[].class);
main.invoke(null,(Object) new String[]{"q","e","r"});
System.out.println(main);
}
六、通过反射运行配置文件内容
当需要从调用第一个业务方法,切换到调用第二个业务方法的时候,不需要修改一行代码,也不需要重新编译,只需要修改配置文件spring.txt,再运行即可。
泛型是在编译期间起作用的。在编译后的.class文件中是没有泛型的。所有比如T或者E类型啊,本质都是通过Object处理的。所以可以通过使用反射来越过泛型。
spring.txt
class=com.zgq.service.impl.UserService1
method=doService1
public class UserService2 {
public void doService2(){
System.out.println("service2=========");
}
}
public class UserService1 {
public void doService1(){
System.out.println("service1=========");
}
}
class ReflexDemo3{
public static void main(String[] args) throws Exception {
Properties springConfig = new Properties();
springConfig.load(new FileInputStream(new File("E:\\WORK_SPACE\\newWorkSpace\\demo\\src\\spring.txt")));
String className = (String)springConfig.get("class");
String method = (String)springConfig.get("method");
Class<?> aClass = Class.forName(className);
Method m = aClass.getMethod(method);
Object o = aClass.getConstructor(null).newInstance();
m.invoke(o);
}
public class GenericityTest {
public static void main(String[] args) throws Exception{
ArrayList<String> list = new ArrayList<>();
list.add("this");
list.add("is");
Class listClass = list.getClass();
Method m = listClass.getMethod("add", Object.class);
m.invoke(list, 5);
}
}