反射和注解

反射和注解,第1张

反射和注解 Java反射机制和注解
  • 动静态语言(了解)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Est7l1PE-1638439101772)(D:MarkDown学习imgsreflect1.png)]

    • 反射:将静态语言转换为动态语言机制

      代码案例:

    function f() {
        //静态字符串
        var x = "var a=3,var b=5,alert(a+b)";
        
        eval(x);
    }
    
一、Java反射机制概述

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YYEl0767-1638439101775)(D:MarkDown学习imgsreflect2.png)]

1>反射机制研究及应用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NoCzWKb5-1638439101776)(D:MarkDown学习imgsreflect3.png)]

2>反射的优缺点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-57sm3gXu-1638439101778)(D:MarkDown学习imgsreflect4.png)]

3>反射相关的主要API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jmeaXev0-1638439101786)(D:MarkDown学习imgsreflect5.png)]

二、理解Class类并获取Class实例 1>Class类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-62e2pkdw-1638439101789)(D:MarkDown学习imgsreflect6-1638282179013.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ExPkVAe0-1638439101791)(D:MarkDown学习imgsreflect7-1638282184763.png)]

  • 代码案例:

    package com.cn.reflect;
    
    //什么叫反射
    public class Test extends Object{
        public static void main(String[] args) throws ClassNotFoundException {
            //通过反射获取类class的对象
            Class c1 = Class.forName("com.cn.reflect.User");
            System.out.println(c1); //class com.cn.reflect.User
    
            Class c2 = Class.forName("com.cn.reflect.User");
            Class c3 = Class.forName("com.cn.reflect.User");
            Class c4 = Class.forName("com.cn.reflect.User");
    
            //一个类在内存中只有一个Class对象
            //一个类被加载后,类的整个结构都会被封装在Class对象中
            System.out.println(c2.hashCode()); //1163157884
            System.out.println(c3.hashCode()); //1163157884
            System.out.println(c4.hashCode()); //1163157884
        }
    }
    //实体类:pojo entity
    class User{
        private String name;
        private int id;
        private int age;
    
        public User() {
        }
    
        public User(String name, int id, int age) {
            this.name = name;
            this.id = id;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + ''' +
                    ", id=" + id +
                    ", age=" + age +
                    '}';
        }
    }
    
2>Class类的常用方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MgFrUPe3-1638439101797)(D:MarkDown学习imgsreflect8-1638282189865.png)]

3>获取Class类的实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6IYiinzK-1638439101799)(D:MarkDown学习imgsreflect9.png)]

  • 代码案例:

    package com.cn.reflect;
    
    //测试Class类的创建方式
    public class Test01 {
        public static void main(String[] args) throws ClassNotFoundException {
    
            //多态
            Person person = new Student();
            //这个人是学生
            System.out.println("这个人是"+person.name);
    
            //方式一:通过对象获得
            Class c1 = person.getClass();
            //1163157884
            System.out.println(c1.hashCode());
    
            //方式二:通过forName获得
            Class c2 = Class.forName("com.cn.reflect.Student");
            //1163157884
            System.out.println(c2.hashCode());
    
            //方式三:通过类名.Class获得
            Class c3 = Student.class;
            //1163157884
            System.out.println(c3.hashCode());
    
            //方式四:基本内置类的包装类都有一个Type属性
            Class c4 = Integer.TYPE;
            System.out.println(c4); //int
    
            //获得父类类型
            Class c5 = c1.getSuperclass();
            System.out.println(c5); //class com.cn.reflect.Person
        }
    }
    class Person{
        public String name;
    
        public Person() {
        }
    
        public Person(String name) {
            this.name = name;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + ''' +
                    '}';
        }
    }
    //学生类
    class Student extends Person{
        public Student() {
            this.name="学生";
        }
    }
    //老师类
    class Teacher extends Person{
        public Teacher() {
            this.name="老师";
        }
    }
    
4>哪些类型可以有Class对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GtxrncOs-1638439101802)(D:MarkDown学习imgsreflect10.png)]

  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.annotation.ElementType;
    
    //所有类型的Class
    public class Test02 {
        public static void main(String[] args) {
            //类
            Class c1 = Object.class;
            //接口
            Class c2 = Comparable.class;
            //一维数组
            Class c3 = String[].class;
            //二维数组
            Class c4 = int[][].class;
            //注解
            Class c5 = Override.class;
            //枚举
            Class c6 = ElementType.class;
            //基本数据类型
            Class c7 = Integer.class;
            //void
            Class c8 = void.class;
            //Class类
            Class c9 = Class.class;
    
            System.out.println(c1); //class java.lang.Object
            System.out.println(c2); //interface java.lang.Comparable
            System.out.println(c3); //class [Ljava.lang.String;
            System.out.println(c4); //class [[I
            System.out.println(c5); //interface java.lang.Override
            System.out.println(c6); //class java.lang.annotation.ElementType
            System.out.println(c7); //class java.lang.Integer
            System.out.println(c8); //void
            System.out.println(c9); //class java.lang.Class
    
            //两个数组的长度不同,类型相同,hashCode值是相同的
            //只要元素类型与维度一样,就是同一个Class
            int[] a = new int[10];
            int[] b = new int[100];
            //1163157884
            System.out.println(a.getClass().hashCode());
            //1163157884
            System.out.println(b.getClass().hashCode());
        }
    }
    
5>知识点拓展(java内存分析)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bXx20XY7-1638439101804)(D:MarkDown学习imgsreflect11.png)]

三、类的加载与CalssLoader 1>类加载的过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0gv9vneo-1638439101805)(D:MarkDown学习imgsreflect12.png)]

2>类的加载与CalssLoader的理解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tx4dP0Au-1638439101807)(D:MarkDown学习imgsreflect13.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lgzu87fX-1638439101808)(D:MarkDown学习imgsreflect14.png)]

  • 代码案例:

    package com.cn.reflect;
    
    //类的加载
    public class Test05 {
        public static void main(String[] args) {
            A a = new A();
            
            
            System.out.println(A.m);
        }
    }
    class A{
        //静态代码块
        static {
            System.out.println("A类静态代码块的初始化");
            m = 300;
        }
        static int m = 100;
    
        public A() {
            System.out.println("A类的无参构造初始化");
        }
    }
    
3>类的初始化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z7bL7HIP-1638439101809)(D:MarkDown学习imgsreflect15.png)]

  • 代码案例:

    package com.cn.reflect;
    
    //测试类什么时候初始化
    public class Test03 {
        static {
            System.out.println("Main类被加载");
        }
    
        public static void main(String[] args) throws ClassNotFoundException {
            
            //1.主动引用
            //Son son = new Son();
            
            //2.反射也会产生主动引用
            //Class.forName("com.cn.reflect.Son");
            
    
            //3.不会产生类的引用的方法
            //System.out.println(Son.b);
            
    
            //4.数组定义类引用
            //Son[] array = new Son[5]; //Main类被加载
    
            //5.引用常量
            System.out.println(Son.M); //Main类被加载 1
        }
    }
    class Father{
        static int b = 2;
        static {
            System.out.println("父类被加载");
        }
    }
    class Son extends Father{
        static {
            System.out.println("子类被加载");
            m = 300;
        }
        static int m = 100;
        static final int M = 1;
    }
    
4>类加载器的作用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hC90sHw2-1638439101810)(D:MarkDown学习imgsreflect16.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZucYzHSw-1638439101811)(D:MarkDown学习imgsreflect17.png)]

  • 代码案例:

    package com.cn.reflect;
    
    //系统类加载器
    
    public class Test04 {
        public static void main(String[] args) throws ClassNotFoundException {
    
            //获取系统类的加载器![在这里插入图片描述](https://img-blog.csdnimg.cn/dfc2bdd2d25c4f9a8086542d2669b588.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASVRf5ZCR5bem5L2_,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
    
            ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
            //sun.misc.Launcher$AppClassLoader@18b4aac2
            System.out.println(systemClassLoader);
    
            //获取系统类加载器的父类加载器-->扩展类加载器
            ClassLoader parent = systemClassLoader.getParent();
            //sun.misc.Launcher$ExtClassLoader@4554617c
            System.out.println(parent);
    
            //获取扩展类加载器的父类加载器-->根加载器(c/c++)
            ClassLoader parent1 = parent.getParent();
            System.out.println(parent1);   //null
    
            //测试当前类是哪个类加载器加载的
     ClassLoader classLoader =Class.forName("com.cn.reflect.Test04").getClassLoader();
            //sun.misc.Launcher$AppClassLoader@18b4aac2
            System.out.println(classLoader);
    
            //测试JDK内置类是哪个类加载器加载的
     ClassLoader classLoader1 = Class.forName("java.lang.Object").getClassLoader();
            System.out.println(classLoader1); //null
    
            //如何获取系统类加载器可以加载的路径
            String property = System.getProperty("java.class.path");
            System.out.println(property);
            
        }
    }
    
5>双亲委派机制(了解)
  • 什么事双亲委派机制

    当某个类加载器需要加载某个.class文件时,它首先把这个任务委托给他的上级类加载器,递归这个 *** 作,如果上级的类加载器没有加载,自己才会去加载这个类
    
  • 双亲委派机制的作用

    1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。
    2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.class,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。
    
  • 源码分析

    protected Class loadClass(String name, boolean resolve)
                throws ClassNotFoundException
        {
            synchronized (getClassLoadingLock(name)) {
                // 首先检查这个classsh是否已经加载过了
                Class c = findLoadedClass(name);
                if (c == null) {
                    long t0 = System.nanoTime();
                    try {
                        // c==null表示没有加载,如果有父类的加载器则让父类加载器加载
                        if (parent != null) {
                            c = parent.loadClass(name, false);
                        } else {
                            //如果父类的加载器为空 则说明递归到bootStrapClassloader了
                            //bootStrapClassloader比较特殊无法通过get获取
                            c = findBootstrapClassOrNull(name);
                        }
                    } catch (ClassNotFoundException e) {}
                    if (c == null) {
                        //如果bootstrapClassLoader 仍然没有加载过,则递归回来,尝试自己去加载class
                        long t1 = System.nanoTime();
                        c = findClass(name);
                        sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                        sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                        sun.misc.PerfCounter.getFindClasses().increment();
                    }
                }
                if (resolve) {
                    resolveClass(c);
                }
                return c;
            }
        }
    

    委派机制的流程图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X3d37jaU-1638439101812)(D:MarkDown学习imgsreflect18.png)]

当一个Hello.class这样的文件要被加载时。不考虑我们自定义类加载器,首先会在AppClassLoader中检查是否加载过,如果有那就无需再加载了。如果没有,那么会拿到父加载器,然后调用父加载器的loadClass方法。父类中同理也会先检查自己是否已经加载过,如果没有再往上。注意这个类似递归的过程,直到到达Bootstrap classLoader之前,都是在检查是否加载过,并不会选择自己去加载。直到BootstrapClassLoader,已经没有父加载器了,这时候开始考虑自己是否能加载了,如果自己无法加载,会下沉到子加载器去加载,一直到最底层,如果没有任何加载器能加载,就会抛出ClassNotFoundException。
  • 为什么要设计这种机制
    这种设计有个好处是,如果有人想替换系统级别的类:String.java。篡改它的实现,在这种机制下这些系统的类已经被Bootstrap classLoader加载过了(为什么?因为当一个类需要加载的时候,最先去尝试加载的就是BootstrapClassLoader),所以其他类加载器并没有机会再去加载,从一定程度上防止了危险代码的植入。
    

    总结

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q1xIZMmU-1638439101813)(D:MarkDown学习imgsreflect19.png)]

四、获取运行时类的对象 1>获取类的运行时结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVzdbKnD-1638439101814)(D:MarkDown学习imgsreflect20.png)]

  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    
    //获取类的信息
    public class Test06 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
            Class c1 = Class.forName("com.cn.reflect.User");
    
            //获得类的名字
            String name = c1.getName();
            System.out.println(name); //com.cn.reflect.User
            String simpleName = c1.getSimpleName();
            System.out.println(simpleName); //User
            System.out.println("=====================");
    
            //获得类的属性
            Field[] fields = c1.getFields(); //只能找到public属性
            fields = c1.getDeclaredFields(); //找到全部属性
            for (Field field : fields) {
                
                System.out.println(field);
            }
            System.out.println("=====================");
            //获得指定属性的值
            Field names = c1.getDeclaredField("name");
            //private java.lang.String com.cn.reflect.User.name
            System.out.println(names);
    
            //获得类的方法
            Method[] methods = c1.getMethods(); //获得本类及父类全部的public方法
            for (Method method : methods) {
                System.out.println("正常的"+method);
            }
            methods = c1.getDeclaredMethods(); //获得本类的所有方法
            for (Method method : methods) {
                System.out.println("DeclaredMethods"+method);
            }
            
            System.out.println("=====================");
            //获得指定方法
            Method getName = c1.getMethod("getName", null);
            Method setName = c1.getMethod("setName", String.class);
            //public java.lang.String com.cn.reflect.User.getName()
            System.out.println(getName);
            //public void com.cn.reflect.User.setName(java.lang.String)
            System.out.println(setName);
            System.out.println("=====================");
            //获得指定的构造器
            //获得本类及父类全部的构造方法
            Constructor[] constructors = c1.getConstructors();
            for (Constructor constructor : constructors) {
                //public com.cn.reflect.User()
                //public com.cn.reflect.User(java.lang.String,int,int)
                System.out.println(constructor);
            }
            //获得本类中所有的构造方法
            Constructor[] declaredConstructors = c1.getDeclaredConstructors();
            for (Constructor declaredConstructor : declaredConstructors) {
                //public com.cn.reflect.User()
                //public com.cn.reflect.User(java.lang.String,int,int)
                System.out.println(declaredConstructor);
            }
    
            //获得指定的构造器
            Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
            //指定:public com.cn.reflect.User(java.lang.String,int,int)
            System.out.println("指定:"+declaredConstructor);
        }
    }
    
2>创建对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8JMU7HLY-1638439101815)(D:MarkDown学习imgsreflect21.png)]

3>调用方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mx0M0Bm5-1638439101816)(D:MarkDown学习imgsreflect22.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upWnKqJo-1638439101816)(D:MarkDown学习imgsreflect23.png)]

4>setAccessible()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7WbPc6tN-1638439101817)(D:MarkDown学习imgsreflect24.png)]

  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    //通过反射动态创建对象
    public class Test07 {
        public static void main(String[] args) throws ClassNotFoundException,
                IllegalAccessException, InstantiationException, NoSuchMethodException,
                InvocationTargetException, NoSuchFieldException {
            //获得Class对象
            Class c1 = Class.forName("com.cn.reflect.User");
    
            //构造一个对象
            User user = (User) c1.newInstance(); //本质是调用无参构造器
            //User{name='null', id=0, age=0}
            System.out.println(user);
            System.out.println("=============================");
    
            //通过构造器创建对象
            Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
            User user1 = (User) constructor.newInstance("张三", 1001, 22);
            //User{name='张三', id=1001, age=22}
            System.out.println(user1);
            System.out.println("=============================");
    
            //通过反射调用普通方法
            User user2 = (User) c1.newInstance();
            //通过反射获取一个方法
            Method setName = c1.getDeclaredMethod("setName", String.class);
            //invoke:激活 (对象,“方法的值”)
            setName.invoke(user2,"李四");
            //李四
            System.out.println(user2.getName());
    
            //通过反射 *** 作属性的值
            User user3 = (User) c1.newInstance();
            //获得指定的属性
            Field name = c1.getDeclaredField("name");
            //不能直接 *** 作私有属性,需关闭程序的安全检测,属性或方法的setAccessible(true)
            name.setAccessible(true);
            name.set(user3,"王五");
            //王五
            System.out.println(user3.getName());
        }
    }
    
5>性能对比分析
  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    
    //分析性能问题
    public class Test08 {
    
        public static void main(String[] args) throws NoSuchMethodException,
                IllegalAccessException, InvocationTargetException {
            test01(); //普通方式执行10万次需要:3ms
            test02(); //反射方式执行10万次需要:33ms
            test03(); //反射方式关闭检测执行10万次需要:5ms
        }
    
        //普通方式调用
        public static void test01(){
            User user = new User();
            //测试程序执行的时长
            //开始时间
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100000; i++) {
                user.getName();
            }
            //结束时间
            long endtTime = System.currentTimeMillis();
            //输出
            System.out.println("普通方式执行10万次需要:"+(endtTime-startTime)+"ms");
        }
    
        //反射方式调用
        public static void test02() throws NoSuchMethodException,
                InvocationTargetException, IllegalAccessException {
            User user = new User();
            Class c1 = user.getClass();
            //获取方法
            Method getName = c1.getDeclaredMethod("getName", null);
            //测试程序执行的时长
            //开始时间
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100000; i++) {
                getName.invoke(user,null);
            }
            //结束时间
            long endtTime = System.currentTimeMillis();
            //输出
            System.out.println("反射方式执行10万次需要:"+(endtTime-startTime)+"ms");
        }
    
        //反射方式调用,关闭检测
        public static void test03() throws NoSuchMethodException,
                InvocationTargetException, IllegalAccessException {
            User user = new User();
            Class c1 = user.getClass();
            //获取方法
            Method getName = c1.getDeclaredMethod("getName", null);
            //设置权限
            getName.setAccessible(true);
            //测试程序执行的时长
            //开始时间
            long startTime = System.currentTimeMillis();
            for (int i = 0; i < 100000; i++) {
                getName.invoke(user,null);
            }
            //结束时间
            long endtTime = System.currentTimeMillis();
            //输出
            System.out.println("反射方式关闭检测执行10万次需要:"+(endtTime-startTime)+"ms");
        }
    }
    
6>获取泛型信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1PCnjBH3-1638439101818)(D:MarkDown学习imgsreflect25.png)]

  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.reflect.Method;
    import java.lang.reflect.ParameterizedType;
    import java.lang.reflect.Type;
    import java.util.List;
    import java.util.Map;
    
    //通过反射获取泛型
    public class Test09 {
    
        //作为参数类型
        public void test01(Map map, List list){
            System.out.println("test01");
        }
        //作为返回值类型
        public Map test02(){
            System.out.println("test02");
            return null;
        }
    
        public static void main(String[] args) throws NoSuchMethodException {
            //通过反射获取方法
            Method method = Test09.class.getMethod("test01", Map.class, List.class);
            //获取参数类型
            Type[] genericParameterTypes = method.getGenericParameterTypes();
            //遍历泛型的参数类型
            for (Type genericParameterType : genericParameterTypes) {
                //***:java.util.Map
                //***:java.util.List
                System.out.println("***:"+genericParameterType);
                //判断泛型的参数类型是否属于参数化类型
                if (genericParameterType instanceof ParameterizedType){
                    //获得真实类型
                    Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                    //遍历真实类型
                    for (Type actualTypeArgument : actualTypeArguments) {
                        //***:java.util.Map
                        //真实类型信息:class java.lang.String
                        //真实类型信息:class com.cn.reflect.User
                        //***:java.util.List
                        //真实类型信息:class com.cn.reflect.User
                        System.out.println("真实类型信息:"+actualTypeArgument);
                    }
                }
            }
            System.out.println("======================================");
            method = Test09.class.getMethod("test02", null);
            //获取返回值类型
            Type genericReturnType = method.getGenericReturnType();
            if (genericReturnType instanceof ParameterizedType){
                //获得真实类型
                Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
                //遍历真实类型
                for (Type actualTypeArgument : actualTypeArguments) {
                    //真实类型信息:class java.lang.String
                    //真实类型信息:class com.cn.reflect.User
                    System.out.println("真实类型信息:"+actualTypeArgument);
                }
            }
        }
    }
    
7>获取注解信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4YNGOAZZ-1638439101818)(D:MarkDown学习imgsreflect26.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JvJiZ9K2-1638439101819)(D:MarkDown学习imgsreflect27.png)]

  • 代码案例:

    package com.cn.reflect;
    
    import java.lang.annotation.*;
    import java.lang.reflect.Field;
    
    //练习反射 *** 作注解
    public class Test10 {
        public static void main(String[] args) throws ClassNotFoundException,
                NoSuchFieldException {
    
            //获得类的对象
            Class c1 = Class.forName("com.cn.reflect.Stu");
            //通过反射获得注解
            Annotation[] annotations = c1.getAnnotations();
            for (Annotation annotation : annotations) {
                //@com.cn.reflect.Stu$Tables(value=db_student)
                System.out.println(annotation);
            }
    
            //获得注解Value的值
            Stu.Tables table = (Stu.Tables) c1.getAnnotation(Stu.Tables.class);
            String value = table.value();
            //db_student
            System.out.println(value);
    
            //获得类的指定注解
            Field field = c1.getDeclaredField("name");
            Stu.Field annotation = field.getAnnotation(Stu.Field.class);
            //db_name
            //varchar
            //50
            System.out.println(annotation.columnName());
            System.out.println(annotation.type());
            System.out.println(annotation.length());
    
        }
    }
    //创建一个实体类
    @Stu.Tables("db_student")
    class Stu{
        @Field(columnName = "db_name",type = "varchar",length = 50)
        private String name;
        @Field(columnName = "db_id",type = "int",length = 20)
        private int id;
        @Field(columnName = "db_age",type = "int",length = 20)
        private int age;
    
        public Stu() {
        }
    
        public Stu(String name, int id, int age) {
            this.name = name;
            this.id = id;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Stu{" +
                    "name='" + name + ''' +
                    ", id=" + id +
                    ", age=" + age +
                    '}';
        }
        //类名的注解
        @Target(ElementType.TYPE)
        @Retention(RetentionPolicy.RUNTIME)
        @interface Tables{
            String value();
        }
        //属性的注解
        @Target(ElementType.FIELD)
        @Retention(RetentionPolicy.RUNTIME)
        @interface Field{
            String columnName();
            String type();
            int length();
        }
    }
    
五、注解 1>什么是注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P4vY4I8p-1638439101820)(D:MarkDown学习imgsanno1.png)]

2>内置注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dtYNHNI7-1638439101820)(D:MarkDown学习imgsanno2.png)]

3>自定义注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xF5pD81e-1638439101854)(D:MarkDown学习imgsanno3.png)]

4>元注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lv17AuXZ-1638439101857)(D:MarkDown学习imgsanno4.png)]

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5636754.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存