不对的地方,希望大佬指正。
什么是反射?
每个类都有对应的类对象,该类对象包含该类的属性方法等信息,这个类对象就是这个类的反射。
获取类对象有以下三种方法:
//用户类
package com.demo.springbootdemo;
/**
* @ClassName: User
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:03
* @Version: 1.0
*/
public class User {
public String username;
public String password;
public User(String username, String password) {
this.username = username;
this.password = password;
}
public void say() {
System.out.println("我的用户名:" + username + ",我的密码:" + password);
}
public void setUsername(String username){
this.username = username;
}
}
//获取类对象
package com.demo.springbootdemo;
/**
* @ClassName: Test08
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:02
* @Version: 1.0
*/
public class Test08 {
public static void main(String[] args) throws Exception {
//第一种
Class a = Class.forName("com.demo.springbootdemo.User");
//第二种
Class b = User.class;
//第三种
Class c = new User().getClass();
//类对象有且只有一个,因此a,b,c三个是相等的,还有一个注意的点是,如果类中包含静态代码块,那么除了User.class这种方法外的另外两种方法,都会造成静态代码块的执行,且只执行一次
}
}
反射的作用?
1、用来创建对象
package com.demo.springbootdemo;
import java.lang.reflect.Constructor;
/**
* @ClassName: Test08
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:02
* @Version: 1.0
*/
public class Test08 {
public static void main(String[] args) throws Exception {
Class a = Class.forName("com.demo.springbootdemo.User");
//参数是构造器中的参数类型
Constructor constructor = a.getConstructor(String.class, String.class);
//参数类型和数量要与构造器一致
User user = (User) constructor.newInstance("admin", "123");
user.say();
}
}
2、用来访问属性
package com.demo.springbootdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
/**
* @ClassName: Test08
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:02
* @Version: 1.0
*/
public class Test08 {
public static void main(String[] args) throws Exception {
Class a = Class.forName("com.demo.springbootdemo.User");
Constructor constructor = a.getConstructor(String.class, String.class);
User user = (User) constructor.newInstance("admin", "123");
user.say();
Field field = user.getClass().getField("username");
field.set(user, "sysadmin");
user.say();
}
}
3、用来访问方法
package com.demo.springbootdemo;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* @ClassName: Test08
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:02
* @Version: 1.0
*/
public class Test08 {
public static void main(String[] args) throws Exception {
Class a = Class.forName("com.demo.springbootdemo.User");
Constructor constructor = a.getConstructor(String.class, String.class);
User user = (User) constructor.newInstance("admin", "123");
Method method = user.getClass().getMethod("say");
method.invoke(user);
user.getClass().getMethod("setUsername", String.class).invoke(user,"test");
method.invoke(user);
}
}
实际应用
前面的例子看着好像反射没什么用,实际反射是下面这么用的,通过修改配置文件,可以在不修改原程序的情况下,分别对不同的类进行访问处理
//我有两个服务类
//第一个
package com.demo.springbootdemo;
/**
* @ClassName: Service1
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:31
* @Version: 1.0
*/
public class Service1 {
public void say(){
System.out.println("i am service1");
}
}
//第二个
package com.demo.springbootdemo;
/**
* @ClassName: Service2
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 17:31
* @Version: 1.0
*/
public class Service2 {
public void doSomething(){
System.out.println("i am service2,i will doSomething");
}
}
//然后通过反射写个main方法,这个方法中没有出现这两个服务类的任何信息,只出现了一个配置文件
package com.demo.springbootdemo;
import java.io.File;
import java.io.FileInputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @ClassName: Test07
* @Author: zhanghongkai
* @Date: Create in 2019/2/15 14:38
* @Version: 1.0
*/
public class Test07 {
public static void main(String[] args) throws Exception {
File file = new File("F:/prop.txt");
Properties properties = new Properties();
properties.load(new FileInputStream(file));
String classKey = properties.getProperty("class");
String methodKey = properties.getProperty("method");
Class<?> c = Class.forName(classKey);
Constructor<?> constructor = c.getConstructor();
Object object = constructor.newInstance();
Method method = c.getMethod(methodKey);
method.invoke(object);
}
}
//配置文件如下
class = com.demo.springbootdemo.Service2
method = doSomething