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> 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);
    }
}
  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值