• 反射和四种元注解


    反射

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

    反射的作用:

    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("
    --------------------------");
            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);
        }
    }
  • 相关阅读:
    课堂讨论及思考
    问题账户需求分析
    阅读计划
    我们应当怎样做需求分析
    常用JavaScript触发事件
    form表单的字符串进行utf-8编码
    关于编码
    JavaScript弹窗
    测试
    感谢博客园
  • 原文地址:https://www.cnblogs.com/TFE-HardView/p/11052392.html
Copyright © 2020-2023  润新知