Java可以使用反射,通过对象来获取对象所属的类的完整结构,包括:变量、方法、构造器、父类、注解和接口
以下例子我们会使用该User类进行举例:
// 实体类
class User{
public String name;
private int id;
private int age;
public User(){ }
public User(String name, int id, int age) {
this.name = name;
this.id = id;
this.age = age;
}
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;
}
1.获取类的名字
使用Class对象中的getName()获取包名+类名;使用getSimpleName()获取类名
public class Test04 {
public static void main(String[] args) throws ClassNotFoundException {
Class c1 = Class.forName("reflection.User");
// 获取类的名字:
System.out.println(c1.getName()); // 获取包名+类名
System.out.println(c1.getSimpleName()); // 仅获取类名
}
}
2.获取类的属性
使用Class对象中的getFields()来获取public属性的变量,而getDeclaredFields()可以获取全部属性,另外,使用c1.getField(String name)来获取特定的属性,当然,如果属性是私有的,则使用getDeclaredField(String name)
Class c1 = Class.forName("reflection.User");
Field[] fields = c1.getFields();
Field[] fields1 = c1.getDeclaredFields();
Field name = c1.getField("name");
Field id = c1.getDeclaredField("id");
3.获取类的方法
使用Class对象中的getMethods()来获取public属性的方法,需要注意的是,这个方法除了会获取本类的方法,同时也会获取其继承的父类的方法。而getDeclaredtMethods()可以获取本类全部方法,不包含父类
另外,使用c1.getMethod(String name, Class[] argTypes)来获取特定的方法,name参数传入方法名,argTypes则是需要传入该方法的参数类型,因为Java中存在重载机制,如果不传入参数类型,可能会无法区分重载的各个方法
4.获取指定的构造器
使用getConstructors()来获取当前对象所属类的所有的构造器,也就是获取类的构造方法,如果构造方法是私有的,那么可以使用getDeclaredConstructors()来获取
那么我们获取到这些对象之后,可以怎么使用呢?我们可以通过这些然后使用反射机制动态创建对象
// 获取User类的Class
Class c1 = Class.forName(com.User);
User user = (User)c1.newINstance(); //调用了User的无参构造器,类中必须要有无参构造方法
当然,上面既然介绍了如何获得构造器,那么我们也可以通过构造器创建对象。这种方法可以调用带参数的构造器动态构造方法
Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
User user = constructor.newInstance("张三",114514,24);
除了动态创建函数,还可以动态执行方法:
// 通过反射获取方法
Method setAge = c1.getDeclaredMethod("setAge", int.class);
// invoke函数,用于激活一个方法
setAge.invoke(user,24);
很显然,invoke方法除了需要传入参数之外,还需要指定该函数执行的对象是哪个
需要注意的是,反射方式相比于普通方法更加消耗资源。