反射和四种元注解

反射

反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性。

 

反射的作用:

Java反射机制提供了以下的功能 在运行时获取类的修饰符,包名,类名,实现的接口,继承的父类

在运行时获取类的所有属性名,修饰符,属性类型

在运行时获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型

在运行时调用加载类的方法

 

Java中的四种元注解:

 @Retention:注解的保留位置         

      @Retention(RetentionPolicy.SOURCE)   //注解仅存在于源码中,在class字节码文件中不包含

      @Retention(RetentionPolicy.CLASS)     // 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得,

      @Retention(RetentionPolicy.RUNTIME)  // 注解会在class字节码文件中存在,在运行时可以通过反射获取到

  

  @Target:注解的作用目标        

        @Target(ElementType.TYPE)   //接口、类、枚举、注解

        @Target(ElementType.FIELD) //字段、枚举的常量

        @Target(ElementType.METHOD) //方法

        @Target(ElementType.PARAMETER) //方法参数

        @Target(ElementType.CONSTRUCTOR)  //构造函数

        @Target(ElementType.LOCAL_VARIABLE)//局部变量

        @Target(ElementType.ANNOTATION_TYPE)//注解

        @Target(ElementType.PACKAGE) ///包   

 

     @Document:说明该注解将被包含在javadoc中

 

   @Inherited:说明子类可以继承父类中的该注解

 

一、自定义注解

//自定义注解
//注释可用在类、成员变量、方法、构造函数上
@Target({ElementType.TYPE,ElementType.FIELD,ElementType.METHOD,ElementType.CONSTRUCTOR})
@Documented//文档注解
@Inherited//可继承,允许子类继承父类的注解
@Retention(RetentionPolicy.RUNTIME)//注解保留在的位置
public @interface StudentAnnotation {
    String name();
    int num();
}

二、创建一个对象类

@StudentAnnotation(name = "我是类", num =123)
public class Student extends Thread implements Runnable,Callable{
    @StudentAnnotation(name = "我是成员变量", num =121)
    private String stuName;
    private int age;
    private String stuNumb;
    @StudentAnnotation(name = "我是带参构造函数", num =121)
    public Student(String stuName, int age, String stuNumb) {        
        this.stuName = stuName;
        this.age = age;
        this.stuNumb = stuNumb;
    }
    @StudentAnnotation(name = "我是无参构造函数", num =126)
    public Student() {        
    }
    @StudentAnnotation(name = "我是方法showInf", num =122)
    public String showInf(){        
        return "姓名是:"+stuName+",年龄是:"+age+",学号是:"+stuNumb;
    }
    @StudentAnnotation(name = "我是方法test", num =122)
    private void test(){
        System.out.println("我是私有方法!test()");
    }    
    
    public String getStuName() {
        return stuName;
    }    
    public void setStuName(String stuName) {
        this.stuName = stuName;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getStuNumb() {
        return stuNumb;
    }
    public void setStuNumb(String stuNumb) {
        this.stuNumb = stuNumb;
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub        
    }
    @Override
    public Object call() throws Exception {
        // TODO Auto-generated method stub
        return null;
    }    
}

三、创建一个测试类,通过反射获取类的信息及属性,方法,构造函数,注解

public class TestCase {    
    public static void main(String[] args) throws Exception {
        TestCase tc=new TestCase();
        //三种获得类名的方式
        Class cla1=Class.forName("ldl.fanshe619.Student");
        Class cla2=Student.class;
        Class cla3=new Student().getClass();
        System.out.println("类名是:"+cla1);        
        tc.getSuperClassOrInterface(cla1);
        System.out.println("\n--------------------------");
        tc.getClassAndModifies(cla1);
        System.out.println("--------------------------");
        tc.getFields(cla1);
        System.out.println("--------------------------");
        tc.getMethods(cla1);
        System.out.println("--------------------------");
        tc.getConstructors(cla1);
        System.out.println("--------------------------");
        tc.getAnnotation(cla1);
    }
    //1.获取类的父类和实现的接口
    public void getSuperClassOrInterface(Class cla) throws Exception{
        String supname=cla.getSuperclass().getName();        
        System.out.println("继承的父类是:"+supname);
        Class[] c1=cla.getInterfaces();
        System.out.print("实现的接口有:");
        for(Class ca:c1){
            System.out.print(ca+",");
        }        
    }
    //2.获取类名和访问修饰符
    public void getClassAndModifies(Class cla){
        //获取类的访问修饰符
        int a=cla.getModifiers();
        Modifier.toString(a);
        System.out.println("类的修饰符是:"+Modifier.toString(a));
    }
    //3.获取所有成员变量
    public void getFields(Class cla) throws Exception{
        //获得所有变量的信息
        Field[] f=cla.getDeclaredFields();
        System.out.println("所有成员变量:");
        for(Field fe:f){
            System.out.println(Modifier.toString(fe.getModifiers())+" "+fe.getType().getSimpleName()+" "+fe.getName());
        }
        //获取单个变量的信息
        Field fe=cla.getDeclaredField("stuName");
        //System.out.println(fe);
        //创建Class对象
        Object obj=cla.newInstance();
        //屏蔽变量的私有特性,并赋值
        fe.setAccessible(true);
        //没有屏蔽私有属性的变量会赋值失败
        fe.set(obj, "张三");        
        Student st=(Student) obj;
        System.out.println("学生名为:"+st.getStuName());
    }
    //4.获取所有成员方法
    public void getMethods(Class cla) throws Exception{
        //获取自己类中的方法(所有的公共方法和私有方法)
        Method[] me=cla.getDeclaredMethods();
        //获取自己类中和所有父类中的所有公共方法
        Method[] me2=cla.getMethods();
        System.out.println("所有成员方法:");
        for(Method meth:me){
            System.out.println(Modifier.toString(meth.getModifiers())+" "+meth.getReturnType().getSimpleName()+" "+
                               meth.getName()+"()"+"{}");
        }
        //获取test方法
        Method mth=cla.getDeclaredMethod("test");
        //屏蔽方法的私有属性
        mth.setAccessible(true);
        //创建对象
        Object obj=cla.newInstance();
        //实现对test方法的调用,invoke中还可传参数(不定长参数)
        mth.invoke(obj);
    }
    //5.获取构造函数
    public void getConstructors(Class cla) throws Exception{
        //获取所有构造函数
        Constructor[] con=cla.getConstructors();
        for(Constructor cons:con){
            System.out.println(cons);
        }
        //获取定义参数的构造函数
        Constructor constr=cla.getConstructor(String.class,int.class,String.class);
        Object obj=constr.newInstance("王庆",18,"12345");
        Student stu=(Student) obj;        
        System.out.println(stu.showInf());
    }
    //6.获取注解
    public void getAnnotation(Class cla) throws Exception{
        StudentAnnotation stu1=(StudentAnnotation) cla.getAnnotation(StudentAnnotation.class);
        System.out.println("类的注解是:"+stu1);
        StudentAnnotation stu2=cla.getDeclaredField("stuName").getAnnotation(StudentAnnotation.class);
        System.out.println("成员变量的注解是:"+stu2);
        StudentAnnotation stu3=cla.getDeclaredMethod("test").getAnnotation(StudentAnnotation.class);
        System.out.println("方法的注解是:"+stu3);
        StudentAnnotation stu4=(StudentAnnotation)cla.getConstructor().getAnnotation(StudentAnnotation.class);
        System.out.println("构造函数的注解是:"+stu4);
    }
}

 

posted @ 2019-06-25 17:00  TFE-HardView  阅读(303)  评论(0编辑  收藏  举报