523

Java中的反射(Reflection)为什么叫“反射”?什么是“正射”?如何自定义注解并解析?

文章目录

反射的定义什么是“正射”反射的作用

反射的定义

计算机科学中的反射(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 createBean(Class 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);

}

}