大家好,我是一个爱举铁的程序员Shr。
本篇文章介绍反射。
源码地址:https://github.com/ShrMus/Dao/tree/master/dao_20180603/src/main/java/com/shrmus/reflex
能够分析类能力的程序成为反射[1]。
在运行中分析类的能力。
在运行中查看对象,例如,编写一个toString方法供所有类使用。
实现通用的数组操作代码。
利用Method对象,这个对象很像C++中的函数指针。
Class类能够保存每个类的信息。
Object类中的getClass()方法可以返回一个Class类的实例。
newInstance() 方法可以创建Class对象所表示的类的一个新实例。
Field类保存类中的字段的信息。
clazz.getFields()方法可以获取类中所有可访问的公共字段。
Constructor类保存类的构造方法的信息。
clazz.getDeclaredConstructor(Class>... parameterTypes)可以获取类的所有带参数或不带参数的构造方法。
Method类保存类的方法的信息。
clazz.getMethod(String name, Class>... parameterTypes)方法可以获得类的所有带参数或者不带参数的公共方法。
method.invoke(Object obj, Object... args)用来执行方法。第一个参数是底层调用该方法的对象,第二个可变参数就是方法的形参。
Modifier类提供了static方法和常量,对类和成员访问修饰符进行解码。
Type接口保存的是类型信息,包括原始类型、参数化类型、数组类型、类型变量和基本类型。
public class Student {
private int id;
private String name;
protected int age;
public int gender;
}
public class StudentTest {
/**
* 反射实例化新对象
*/
@Test
public void newInstance() throws Exception{
// 原对象
Student student = new Student();
System.out.println(student);
// 原对象的Class对象
Class extends Student> clazz = student.getClass();
// 实例化一个新对象
Student newInstance = clazz.newInstance();
System.out.println(newInstance);
// 获取类的全路径
String name = clazz.getName();
System.out.println(name);
}
}
运行结果:
com.shrmus.reflex.Student@69d0a921
com.shrmus.reflex.Student@446cdf90
com.shrmus.reflex.Student
可以看到第一个对象的地址和第二个对象的地址不一样,所以证实了反射实例化的是一个新对象。
/**
* 反射获取字段
*/
@Test
public void getDeclaredFields() throws Exception {
Class clazz = Student.class;
// 根据字段名获取字段的信息
Field field1 = clazz.getDeclaredField("name");
System.out.println(field1.toGenericString());
// 获取类中的所有字段
Field[] fields = clazz.getDeclaredFields();
for(Field field : fields) {
System.out.println(Modifier.toString(field.getModifiers()) + " " + field.getGenericType().getTypeName() + " " + clazz.getName() + "." + field.getName());
}
}
运行结果:
private java.lang.String com.shrmus.reflex.Student.name
private int com.shrmus.reflex.Student.id
private java.lang.String com.shrmus.reflex.Student.name
protected int com.shrmus.reflex.Student.age
public int com.shrmus.reflex.Student.gender
public Student() {
}
public Student(int id) {
this.id = id;
}
public Student(String name) {
this.name = name;
}
private Student(int id,String name) {
this.id = id;
this.name = name;
}
protected Student(int id,String name,int age) {
this.id = id;
this.name = name;
this.age = age;
}
public Student(int id,String name,int age,int gender) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
}
/**
* 反射获取构造方法
*/
@Test
public void getDeclaredConstructors() throws Exception {
Class clazz = Student.class;
// 根据构造方法的参数个数获取构造方法
Constructor constructor1 = clazz.getDeclaredConstructor(Integer.TYPE,String.class,Integer.TYPE);
System.out.println(constructor1.toGenericString());
// 获取所有构造方法
Constructor>[] constructors = clazz.getDeclaredConstructors();
for(Constructor constructor : constructors) {
System.out.print(Modifier.toString(constructor.getModifiers()) + " " + constructor.getName());
// 获取参数类型
Type[] genericParameterTypes = constructor.getGenericParameterTypes();
System.out.print("(");
if(genericParameterTypes.length > 0) {
int length = genericParameterTypes.length;
for(int i = 0; i < length - 1; i++) {
String typeName = genericParameterTypes[i].getTypeName();
System.out.print(typeName + ", ");
}
System.out.print(genericParameterTypes[length - 1].getTypeName());
}
System.out.print(")");
System.out.println();
}
}
运行结果:
protected com.shrmus.reflex.Student(int,java.lang.String,int)
public com.shrmus.reflex.Student(int, java.lang.String, int, int)
protected com.shrmus.reflex.Student(int, java.lang.String, int)
private com.shrmus.reflex.Student(int, java.lang.String)
public com.shrmus.reflex.Student()
public com.shrmus.reflex.Student(int)
public com.shrmus.reflex.Student(java.lang.String)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public int getGender() {
return gender;
}
public void setGender(int gender) {
this.gender = gender;
}
private void test01() throws RuntimeException{
}
protected void test02() throws SQLException{
}
public static String test03() {
return "test03()";
}
public static final Student test04(String string1,Student student) {
System.out.println(string1 + " " + student.getName());
return student;
}
/**
* 反射获取类的所有方法
*/
@Test
public void getDeclaredMethods() throws Exception {
Class extends Student> clazz = Student.class;
// 根据方法名获取方法对象
Method declaredMethod = clazz.getDeclaredMethod("test04",String.class,Student.class);
Student student = clazz.newInstance();
// 执行方法
String string = "haha";
student.setName("张三");
Object invoke = declaredMethod.invoke(student,string,student);
System.out.println(invoke);
// 获取所有方法,不包括构造方法
Method[] declaredMethods = clazz.getDeclaredMethods();
for(Method method : declaredMethods) {
System.out.print(Modifier.toString(method.getModifiers()) + " " + method.getGenericReturnType().getTypeName() + " " + clazz.getName() + "." + method.getName());
// 获取参数类型
Type[] genericParameterTypes = method.getGenericParameterTypes();
System.out.print("(");
if(genericParameterTypes.length > 0) {
int length = genericParameterTypes.length;
for(int i = 0; i < length - 1; i++) {
String typeName = genericParameterTypes[i].getTypeName();
System.out.print(typeName + ", ");
}
System.out.print(genericParameterTypes[length - 1].getTypeName());
}
System.out.print(")");
System.out.println();
}
}
运行结果:
haha 张三
com.shrmus.reflex.Student@446cdf90
public java.lang.String com.shrmus.reflex.Student.getName()
public int com.shrmus.reflex.Student.getId()
public void com.shrmus.reflex.Student.setName(java.lang.String)
public static final com.shrmus.reflex.Student com.shrmus.reflex.Student.test04(java.lang.String, com.shrmus.reflex.Student)
private void com.shrmus.reflex.Student.test01()
public static java.lang.String com.shrmus.reflex.Student.test03()
public int com.shrmus.reflex.Student.getAge()
public int com.shrmus.reflex.Student.getGender()
protected void com.shrmus.reflex.Student.test02()
public void com.shrmus.reflex.Student.setGender(int)
public void com.shrmus.reflex.Student.setId(int)
public void com.shrmus.reflex.Student.setAge(int)
[1] (美)霍斯特曼(Horstmann),科内尔(Cornell).Java核心技术卷1:基础知识(原书第9版)[M].机械工业出版社,2013
源码地址:https://github.com/ShrMus/Dao/tree/master/dao_20180603/src/main/java/com/shrmus/reflex