反射相关知识
- Class
Class类的实例表示正在运行的Java应用程序中的类和接口 - Constructor
关于类的单个构造方法的信息以及对它的访问权限 - Field
Field 提供有关类或接口的单个字段的信息,以及对它的动态访问权限. - Method
Method 提供关于类或接口上单独某个方法的信息 - setAccessible(true);//通过该设置可以访问类中私有属性(可以提高反射执行效率减小程序执行时间)
获取类的方法
已知类和对象的情况下
- 类名.class
- 对象.getClass() — Object 类提供
- 未知类和对象的情况下Class.forName(“包名.类名”)
String path="com.DW.bean.User";//表示User类的全路径名(包名+类名)
Class clazz=Class.forName(path);//通过Class.forName()方法获取类
//获取类名
System.out.println(clazz.getName());//运行结果 包名+类名:com.DW.bean.User
System.out.println(clazz.getSimpleName());//运行结果 类名:User
获取类的属性方法
- getField()和getFields()只能获取public修饰的属性
- getDeclaredField()和getDeclaredFields()可以获取所有属性
//getField()和getFields()只能获取public修饰的属性
Field field=clazz.getField("a");//传入public修饰的属性名返回属性
Field[] fields=clazz.getFields();//获取所有public修饰的属性并返回在数组中
//getDeclaredField()和getDeclaredFields()可以获取所有属性
Field field=clazz.getDeclaredField(); //传入属性名返回属性
Field[] fields=clazz.getDeclaredFields();//返回所有属性返回到数组中
获取类的方法的方法
- .getMethod()和getMethods()可以获取public修饰的方法
- getDeclaredMethod()和getDeclaredMethods()可以获取所有方法
//.getMethod()和getMethods()可以获取public修饰的方法
Method method=clazz.getMethod("");//传入public修饰的方法名返回方法
Method[] methods=clazz.getMethods();//获取所有public修饰的方法并返回在数组中
//getDeclaredMethod()和getDeclaredMethods()可以获取所有方法
Method method=clazz.getDeclaredMethod("getUname");//第一个参数表示方法名称,第二个参数表示方法的参数类型
Method method1=clazz.getDeclaredMethod("setUname", String.class);//String.class表示传入方法的参数类型为string类型
Method[] methods=clazz.getDeclaredMethods();//可以获取所有方法并返回到数组中
获取类构造器方法
1…getConstructor()和getConstructors()可以获取public修饰的方法
2.getDeclaredConstructors();和getDeclaredConstructor()可以获取所有构造方法
// 获取public修饰的构造器
Constructor constructor=clazz.getConstructor();//传入参数类型来获取public修饰的构造器没有参数可以不写
Constructor[] constructors=clazz.getConstructors();
//获取所以构造器
Constructor[] constructors=clazz.getDeclaredConstructors();
Constructor constructor=clazz.getDeclaredConstructor();//传入构造器的参数类型来区分获取的构造器
通过反射动态调用构造器、方法、属性
创建一个bean
package com.DW.bean;
public class User {
private int id;
private int age;
private String uname;
public User() {
}
public User(int id, int age, String uname) {
this.id = id;
this.age = age;
this.uname = uname;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
}
创建测试
import com.DW.bean.User;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
/**
* 通过反射动态调用构造器、方法、属性
*/
public class test02 {
public static void main(String[] args) {
String path="com.DW.bean.User";//表示User类的全路径名(包名+类名)
try {
Class<User> clazz=(Class<User>) Class.forName(path);//通过Class.forName()方法获取类
//通过反射调用构造方法、构造对象
User u=clazz.newInstance();//创建User对象(其实是调用了User的无参构造方法)
//通过有参构造器创建对象
//获取有参构造器
Constructor<User> c=clazz.getDeclaredConstructor(int.class,int.class,String.class);
User u2=c.newInstance(1,1000,"李白");
System.out.println(u2.getUname());
//通过反射调用普通方法
Method method=clazz.getDeclaredMethod("setUname", String.class);
method.invoke(u,"张飞");//相当于u.setUname("张飞");
System.out.println(u.getUname());
//通过反射操作属性
Field f=clazz.getDeclaredField("age");
f.setAccessible(true);//通过该设置可以访问类中私有属性(可以提高反射执行效率)
f.set(u,10);//相当于u.setAge(10);
System.out.println(u.getAge());
} catch (Exception e) {
e.printStackTrace();
}
}
}
反射小案例
需求:写一个“框架”,可以帮我们在不改变任何代码前提下,创建任意类的对象,并且执行其中任意方法
步骤
1. 将需要创建的对象的全类名和要执行的方法定义在配置文件中
2. 在程序中加载读取到的配置文件
3. 使用反射技术来加载类文件进内存
4. 创建对象
5. 执行方法
具体步骤
创建要创建的类
package com.DW;
public class student {
public void eat(){
System.out.println("吃饭");
}
}
编写配置文件(pro.properties)
# 创建类的全类名
className=com.DW.student
# 创建类的方法名
methodName=eat
创建测试类
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
class test {
public static void main(String[] args) throws Exception {
//加载配置文件
Properties pro=new Properties();
//加载配置文件,转化为集合
//通过类加载器获取文件路径
ClassLoader classLoader = test.class.getClassLoader();
InputStream resourceAsStream = classLoader.getResourceAsStream("pro.properties");
pro.load(resourceAsStream);
//获取配置文件内容
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//通过反射加载类创建对象并调用方法
Class aClass = Class.forName(className);
Object o = aClass.newInstance();//创建对象
Method method = aClass.getMethod(methodName);//获取方法
//执行方法
method.invoke(o);
}
}