反射的定义
计算机科学中的反射(reflection) 指计算机程序在运行时(runtime) 可以访问、检测和修改它本身状态或行为的一种能力。通俗说,反射就是程序在运行的时候能够“观察”并且修改自己的行为,是程序对自身的反思、自检、修改。英文 reflection 本身就有反思的意思。而反思一词听起来让程序有了生命力,也说明了反射只有在程序运行时才能起作用,因为程序代码只有在CPU上“跑”起来才有“生命力”。既然有反射那有没有正射呢?
什么是“正射”
在Java程序中,在没有用到反射相关的类的时候,我们都是在做正射。
class Human {
String name;
int age;
String nation;
Human(String name,int age,String nation) {
this.name=name;
this.age=age;
this.nation=nation;
}
void changeName(String name){
this.name=name;
}
}
public class Main {
public static void main(String[] args){
Human human=new Human("张静文",22,"中国");
human.changeName("张文");
}
}
在上面Main类的main方法中,我之所以可以写human.changeName(“张文”) 是因为Human类也是我自己写的,我清楚的知道,human作为Human的实例对象,可以调用changeName方法,如果我手抖写了调用changeNamee方法,我也会立即改回来,因为我知道Human里没有这个方法。假如我不知道Human里有没有一个改名字的方法,即Human类对我来说是不透明的第三方类,我尝试性的在程序中调用了一个newName方法,保存、编译。这时候编译器会通知我,这样写程序是不对的,Human里没有一个叫newName的方法,编译失败。
不管是我们手动纠错还是编译器纠错,对程序本身来说都是外部对自身的修改,由外部“思考”程序究竟能否调用changeName这个方法。而反射做的事就是将这种“思考”交给程序自身,由程序在运行时确定Human中有没有一个叫changeName的方法,进而去调用它。
反射的作用
从反射的定义中我们可以了解到反射的作用,即在运行时访问、修改对象的状态和行为,可以给程序带来极大的灵活性。
使用Java注解配合反射可以开发出各种工具、框架。例如,用自定义注解 @FieldAnnotation 实现为属性赋值。
定义注解 @FieldAnnotation:
package com.houch.annotation;
import java.lang.annotation.*;
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldAnnotation {
String value() default "";
}
编写解析类。BeanFactory中的createBean方法通过反射拿到注解 @FieldAnnotation的值并赋给对象。
package com.houch.annotation;
import java.lang.reflect.Field;
public class BeanFactory {
public static <T> T createBean(Class<T> clazz) {
T o = null;
try {
o = clazz.newInstance();
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
Field[] declaredFields = clazz.getDeclaredFields();
for (Field declaredField : declaredFields) {
if (declaredField.isAnnotationPresent(FieldAnnotation.class)) {
FieldAnnotation fieldAnnotation = declaredField.getAnnotation(FieldAnnotation.class);
if (!declaredField.isAccessible())
declaredField.setAccessible(true);
try {
if (declaredField.getType().getSimpleName().equals("String"))
declaredField.set(o, fieldAnnotation.value());
else if (declaredField.getType().getSimpleName().equals("byte"))
declaredField.set(o, Byte.parseByte(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("short"))
declaredField.set(o, Short.parseShort(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("int"))
declaredField.set(o, Integer.parseInt(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("long"))
declaredField.set(o, Long.parseLong(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("float"))
declaredField.set(o, Float.parseFloat(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("double"))
declaredField.set(o, Double.parseDouble(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("long"))
declaredField.set(o, Long.parseLong(fieldAnnotation.value()));
else if (declaredField.getType().getSimpleName().equals("boolean"))
declaredField.set(o, Boolean.parseBoolean(fieldAnnotation.value()));
else
throw new RuntimeException(declaredField.getName() + " of " + clazz.getName() + " is not a value field");
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
return o;
}
}
实体类:
package com.houch;
import com.houch.annotation.FieldAnnotation;
public class Teacher {
@FieldAnnotation("12138")
private int id;
@FieldAnnotation("Zhang")
private String name;
@FieldAnnotation("24")
private int age;
@FieldAnnotation("false")
private boolean isProfessor;
@FieldAnnotation("M")
private String sex;
@FieldAnnotation("CQU")
private String school;
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public boolean isProfessor() {
return isProfessor;
}
public String getSex() {
return sex;
}
public String getSchool() {
return school;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setProfessor(boolean professor) {
isProfessor = professor;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setSchool(String school) {
this.school = school;
}
@Override
public String toString() {
return "Teacher{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", isProfessor=" + isProfessor +
", sex=" + sex +
", school='" + school + '\'' +
'}';
}
}
测试类
package com.houch;
import com.houch.annotation.BeanFactory;
public class Main {
public static void main(String[] args) {
Teacher teacher = BeanFactory.createBean(Teacher.class);
System.out.println(teacher);
}
}