注解与反射

注解与反射

注解

Annotation是从JDK5.0开始引进的新技术

Annotation的作用:

1. 不是程序本身,可以对程序做出解释
2. 可以被其他程序读取

Annotation的格式:

  1. 注释是以"@注释名"在代码中存在的,还可以添加一些参数值,例如@SuppressWarnings(value=“unchecked”)

Annotation在哪里使用

可以附加在package,class,method,field等上面,相当于给他们添加了额外的辅助信息,我们可以通过反射机制编程实现对这些元数据的访问

元注解

  1. 元注解的作用就是负责注解其他注解,java中定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型的说明

  2. 这些类型和他们所支持的类在java.lang.annotation包中可以找到(@Target,@Retention,@Documented,@Inherited)

@Target:用于描述注解的使用范围(即:被描述的注解可以放在什么地方)

@Retention:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(source<class<runtime)

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

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

public class Test01 {

    @MyAnnotation
    public void test(){

    }
}


//Target 表示我们的注解可以在哪些地方使用
@Target(value = {ElementType.METHOD})
//Rentention表示注解在什么地放才有效
//runtime>class>source
@Retention(value = RetentionPolicy.RUNTIME)
//表示子类可以继承父类的注解
@Inherited
//Documented表示是否将我们的注解生成在javadoc中
@Documented
@interface MyAnnotation{

}

自定义注解

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IuI2HIGK-1641526042686)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702144900431.png)]

//自定义注解

public class Test03 {
   //注解可以显式赋值,如果没有默认值,我们必须给注解赋值
   @MyAnnotation01(age = 18)
   public void test02(){

   }

   @MyAnnotation3("秦疆")
   public void test04(){

   }
}

@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation01{
   //注解的参数:参数类型 + 参数名 ();
   String name() default "";
   int age() ;
   int id() default -1;//  如果默认值为-1,代表不存在,indexof,如果找不到就返回-1

   String[] schools() default {"西部开源","清华大学"};
}

@Target(value = {ElementType.TYPE,ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME)
@interface MyAnnotation3{
   //如果只有一个参数,默认创建的参数名为value()
   String value();
}

反射

反射机制

//什么是反射
public class Test01 {
    public static void main(String[] args) throws ClassNotFoundException {
        //通过反射获取类的class对象
        Class c1 = Class.forName("com.byhz.reflection.User");
        System.out.println(c1);
        Class c2 = Class.forName("com.byhz.reflection.User");
        Class c3 = Class.forName("com.byhz.reflection.User");
        Class c4 = Class.forName("com.byhz.reflection.User");
        
        //返回的hashcode为同一个,所以为同一个类
        System.out.println(c1.hashCode());
        System.out.println(c2.hashCode());
        System.out.println(c3.hashCode());
        System.out.println(c4.hashCode());
    }
}

//实体类
class User{
    private String userName;

    private int id;

    private int age;

    public User() {
    }

    public User(String userName, int id, int age) {
        this.userName = userName;
        this.id = id;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    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;
    }
}

获取Class类的实例

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WBFs880c-1641526042691)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702162117271.png)]

测试Class类的创建方式有哪些
//测试Class类的创建方式有哪些
public class Test02 {

    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Student();
        System.out.println("这个人是:" + person.name);

        //方式一对象名.getClass获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());

        //方式二Class.forName(类的路径)获得
        Class c2 = Class.forName("com.byhz.reflection.Student");
        System.out.println(c2.hashCode());

        //类名.class获得类
        Class c3 = Student.class;
        System.out.println(c3.hashCode());

        //获得父类类型
        Class c4 = c3.getSuperclass();
        System.out.println(c4);

    }

}

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 = "老师";
    }
}

所有类型的Class对象
public class Test03 {
    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;   //基本数据类型
        Class c8 = void.class;  //void
        Class c9 = Class.class; //Class
        
         //只要元素类型与维度一样,就是同一个class
        int[] a = new int[10];
        int[] b =  new int[100];

        System.out.println(c1);
        System.out.println(c2);
        System.out.println(c3);
        System.out.println(c4);
        System.out.println(c5);
        System.out.println(c6);
        System.out.println(c7);
        System.out.println(c8);
        System.out.println(c9);
        System.out.println(a.getClass().hashCode());
        System.out.println(b.getClass().hashCode());
    }
}

//结果
class java.lang.Object
interface java.lang.Comparable
class [Ljava.lang.String;
class [[I
interface java.lang.Override
class java.lang.annotation.ElementType
class java.lang.Integer
void
class java.lang.Class
356573597
356573597        

类加载内存分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qWNRtcX1-1641526042692)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210702165004314.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GwUNYuey-1641526042694)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705112623066.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bnMlRSET-1641526042696)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705112703020.png)]

public class Test04 {

    public static void main(String[] args) throws ClassNotFoundException {
        //获取系统类的加载器
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);


        //获取 系统类加载器的父类加载器 --> 扩展类加载器
        ClassLoader parent = systemClassLoader.getParent();
        System.out.println(parent);


        //获取扩展类加载器的父类加载器---> 根加载器
        ClassLoader parent1 = parent.getParent();
        System.out.println(parent1);


        //测试当前类是哪个加载器加载的
        ClassLoader classLoader = Class.forName("com.byhz.reflection.Test04").getClassLoader();
        System.out.println(classLoader);

        //测试jdk内置的类是谁加载的
        classLoader = Class.forName("java.lang.Object").getClassLoader();
        System.out.println(classLoader);


        //如何获得系统类加载器可以加载的路径
        String property = System.getProperty("java.class.path");
        System.out.println(property);
        
        

        /**
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;
         * C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;
         * D:\IdeaProjects\practiceFFmpeg\target\classes;
         * D:\IdeaProjects\practiceFFmpeg\src\main\java\lib\commons-io-2.10.0.jar;
         * C:\Program Files\JetBrains\IntelliJ IDEA 2019.3.4\lib\idea_rt.jar
         */
    }
}

获取类运行时结构

//获得类得信息
public class Test05 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.byhz.reflection.User");

        //获得类得名字
        System.out.println(c1.getName());
        System.out.println(c1.getSimpleName());
        /**
         * printResult
         * com.byhz.reflection.User
         * User
         */



        //获得类得属性
        System.out.println("==========================");
        Field[] fields = c1.getFields();//只能找到public属性
        System.out.println(fields);
        fields = c1.getDeclaredFields();//找到全部属性
        for (Field field : fields) {
            System.out.println(field.getName());
        }

        //获得指定属性的值
        Field name = c1.getDeclaredField("userName");
        System.out.println(name);

        //获得类的方法
        System.out.println("==========================");
        Method[] methods = c1.getMethods();//获取本类或者父类的全部public属性
        for (Method method : methods) {
            System.out.println("getMethods:" + method);
        }

        /**
         * 本类和父类的public方法
         * getMethodspublic int com.byhz.reflection.User.getId()
         * getMethodspublic java.lang.String com.byhz.reflection.User.getUserName()
         * getMethodspublic int com.byhz.reflection.User.getAge()
         * getMethodspublic void com.byhz.reflection.User.setAge(int)
         * getMethodspublic void com.byhz.reflection.User.setId(int)
         * getMethodspublic void com.byhz.reflection.User.setUserName(java.lang.String)
         * getMethodspublic final void java.lang.Object.wait() throws java.lang.InterruptedException
         * getMethodspublic final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
         * getMethodspublic final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
         * getMethodspublic boolean java.lang.Object.equals(java.lang.Object)
         * getMethodspublic java.lang.String java.lang.Object.toString()
         * getMethodspublic native int java.lang.Object.hashCode()
         * getMethodspublic final native java.lang.Class java.lang.Object.getClass()
         * getMethodspublic final native void java.lang.Object.notify()
         * getMethodspublic final native void java.lang.Object.notifyAll()
         */
        System.out.println("==========================");
        methods = c1.getDeclaredMethods();//获取本类的所有方法
        for (Method method : methods) {
            System.out.println("getDeclaredMethods:" + method);
        }

        /**
         * 获取本类的所有方法
         * getDeclaredMethodspublic int com.byhz.reflection.User.getId()
         * getDeclaredMethodspublic java.lang.String com.byhz.reflection.User.getUserName()
         * getDeclaredMethodspublic int com.byhz.reflection.User.getAge()
         * getDeclaredMethodspublic void com.byhz.reflection.User.setAge(int)
         * getDeclaredMethodspublic void com.byhz.reflection.User.setId(int)
         * getDeclaredMethodspublic void com.byhz.reflection.User.setUserName(java.lang.String)
         */

        System.out.println("=======================================");

        //获得指定方法
        Method getUserName = c1.getMethod("getUserName", null);
        Method setUserName = c1.getMethod("setUserName", String.class);
        System.out.println(getUserName);
        System.out.println(setUserName);



        System.out.println("=======================================");
        //获得指定指定得构造器
        Constructor[] constructors = c1.getConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        /**
         * public com.byhz.reflection.User()
         * public com.byhz.reflection.User(java.lang.String,int,int)
         */


        System.out.println("============================================");
        constructors = c1.getDeclaredConstructors();
        for (Constructor constructor : constructors) {
            System.out.println(constructor);
        }
        /**
         * public com.byhz.reflection.User()
         * public com.byhz.reflection.User(java.lang.String,int,int)
         */


        System.out.println("============================================");
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("指定构造器为:" + declaredConstructor);

        /**
         * 指定构造器为:public com.byhz.reflection.User(java.lang.String,int,int)
         */
    }
}

动态创建对象执行方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PbHnCtYD-1641526042700)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150018816.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I6zPRH8Y-1641526042702)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150048860.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GsbMm4hi-1641526042705)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150127510.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCSh3yht-1641526042707)(C:\Users\liyeqi\AppData\Roaming\Typora\typora-user-images\image-20210705150229274.png)]

//动态创建对象,通过反射public class Test06 {    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {        //获得Class对象        Class clazz = Class.forName("com.byhz.reflection.User");        //构造一个对象        User user = (User)clazz.newInstance();//本质上是调用了无参构造器        System.out.println(user.toString());        //通过构造器创建对象        Constructor constructor = clazz.getDeclaredConstructor(String.class, int.class, int.class);        User instance = (User)constructor.newInstance("李叶琦", 1, 23);        System.out.println(instance);        //通过反射调用普通方法        User person = (User)clazz.newInstance();        //通过反射获取方法        Method setUserName = clazz.getDeclaredMethod("setUserName", String.class);        //激活        //(对象,"方法的值")        setUserName.invoke(person,"狂神");        System.out.println(person.getUserName());        //通过反射操作属性        User person1 = (User)clazz.newInstance();        Field userName = clazz.getDeclaredField("userName");        System.out.println("=================================");        //不能直接操作私有属性,我们需要关闭程序的安全检测,属性或者方法的setAccessible(true)        userName.setAccessible(true);        userName.set(person1,"狂神2");        System.out.println(person1.getUserName());    }}

性能对比分析

//分析性能问题public class Test07 {    //普通方式调用    public static void test01(){        User user = new User();        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000; i++) {            user.getUserName();        }        long endTime = System.currentTimeMillis();        System.out.println("普通方式执行10亿次:" + (endTime - startTime));    }    //反射调用    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {        User user = new User();        Class c1 = user.getClass();        Method getUserName = c1.getDeclaredMethod("getUserName", null);        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000; i++) {            getUserName.invoke(user,null);        }        long endTime = System.currentTimeMillis();        System.out.println("反射方式执行10亿次:" + (endTime - startTime) + "ms");    }    //反射方式调用  关闭检测    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {        User user = new User();        Class c1 = user.getClass();        Method getUserName = c1.getDeclaredMethod("getUserName", null);        getUserName.setAccessible(true);        long startTime = System.currentTimeMillis();        for (int i = 0; i < 1000000000; i++) {            getUserName.invoke(user,null);        }        long endTime = System.currentTimeMillis();        System.out.println("反射方式关闭检测执行10亿次:" + (endTime - startTime) + "ms");    }    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {        test01();        test02();        test03();        /**         * 普通方式执行10亿次:5         * 反射方式执行10亿次:4716ms         * 反射方式关闭检测执行10亿次:1899ms         */    }}

获取注解信息

//联系反射操作注解public class Test09 {    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {        Class c1 = Class.forName("com.byhz.reflection.Student2");        //通过反射获取注解        Annotation[] annotations = c1.getAnnotations();        for (Annotation annotation : annotations) {            System.out.println(annotation);        }        //获得注解value的值        TableLi tableLi = (TableLi)c1.getAnnotation(TableLi.class);        String value = tableLi.value();        System.out.println(value);        System.out.println("=============================================== ");        Field name = c1.getDeclaredField("id");        FieldKuang annotation = name.getAnnotation(FieldKuang.class);        System.out.println(annotation.columnName());        System.out.println(annotation.length());        System.out.println(annotation.type());     }}@TableLi("db_student")class Student2{    @FieldKuang(columnName = "db_id",type = "int",length = 10 )    private int id;    @FieldKuang(columnName = "db_age",type = "int",length = 10)    private int age;    @FieldKuang(columnName = "db_name",type = "varchar",length = 3)    private String name;    public Student2() {    }    public Student2(int id, int age, String name) {        this.id = id;        this.age = age;        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;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    @Override    public String toString() {        return "student2{" +                "id=" + id +                ", age=" + age +                ", name='" + name + '\'' +                '}';    }}//类名的注解@Target({ElementType.TYPE,ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)@interface TableLi{    String value();}//属性的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)@interface FieldKuang{    String columnName();    String type();    int length();}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值