精选文章 java基础学习笔记(七)-反射--注解

java基础学习笔记(七)-反射--注解

作者:m0_47419463 时间: 2020-08-05 05:12:10
m0_47419463 2020-08-05 05:12:10
反射机制介绍 _Class 对象获取
 
  1. 反射机制是 Java 的动态性之一
    动态语言 : 在程序运行时,可以改变程序的结构或变量的类型。
    典型的动态语言 ”Python ruby JavaScripC,C++, Java 不是动态语言,但具有一定的动态性,可以称为” 准动态语言 ”, 具备类似动态语言的特性。传一块代码来动态的执行,动态的处理,Java 也能做,可以利用反射来实现类似的功能。
    Java 的动态性让编程变得更加的灵活,功能就更加的强大。
  2. 反射机制
    程序在运行的过程中加载一些“只知道相关名字”的类,
    以下代码,在程序运行时加载 User 类。
    Class c=Class.forName("com.zb.reflect.User");
    一个类被加载后, JVM 会创建一个对应类的 Class 对象,
    类的整个结构信息会被放到 Class 对象中。
    这个 Class 对象就像镜子一样,通过这面镜子,可以得到对应类的全部信息。
  3. 反射机制的常见作用
    1) 动态的加载类、动态的获取类的信息 ( 属性,方法,构造器)
    2) 动态构造对象
    3) 动态调用类和对象的任意方法、构造器
    4) 动态调用和处理属性
    5) 获取泛型信息
    6) 处理注解
  4. 获取 Class 对象的方式
    1) 通过字节码文件
    2) 对象的 getClass() 方法                                                                                                                                                            3) Class 类的静态方法 forName(….)
  5. public class Test1 {
        public static void main(String[] args) throws ClassNotFoundException {
            System.out.println(Integer.class);
            System.out.println(int.class);
            System.out.println(void.class);
            //维数相同和类型相同的数组共享同一个Class对象
            int [] array=new int[10];
            int [] array2=new int[30];
            System.out.println(array.getClass()==array2.getClass());
            //同一个类的N多对象,共享同一个Class对象
            User u1=new User();
            User u2=new User();
            System.out.println(u1.getClass()==u2.getClass());
            
            //获取Class对象的三种方法
            Class c1=u1.getClass();
            Class c2=User.class;
            Class c3=Class.forName("day07.reflect.User");
        }
    }

     


反射机制动态操作 _ 方法 _ 属性 _ 构造器
 
  1. 获取类的名字
    方法描述
    String getName()
    获得包名 + 类名
    String getSimpleName()
    获得类的名字
  2. 获得类的属性
    方法描述
    Field getField(String fieldName)
    得到公共的属性对象
    Field getDeclareField(String fieldName)
    得到指定名称的属性对象
    Field []c.getDeclaredFields()
    得到所有的属性对象
  3. 获得类的方法
    方法描述
    Method[] getDeclaredMethods()
    得到公共的方法对象
    Method[] c.getMethods()
    得到父类及本类中的公共的方法对象
    Method getDeclaredMethod(String methodName, Class …type)
    得到指定名称的本类中公共的方法
    Method getMethod(String methodName, Class type)
    得到本类或父类中的公共的方法对象
  4. 获得构造方法
    方法描述
    Constructor[] getDeclaredConstructors()
    得到公共的构造方法的对象
    Constructor [] getConstructors()
    得到公共的构造方法对象
    Constructor getDeclaredConstructor(Class...type)
    得到指定参数的公共的构造方法对象
  5. 动态的操作属性、方法、构造方法
  6. public class Test03 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
            Class c=Class.forName("day07.reflect.User");
            System.out.println(c.getName());//包名
            System.out.println(c.getSimpleName());//类名
            Class cSuper=c.getSuperclass();//得到父类
            Field [] fields1=c.getFields();//只能获取公共属性
            Field [] fields2=c.getDeclaredFields();//获取所有属性
            for(Field field:fields2){
                System.out.println(field);
                                        //访问权限             类型               方法名称
                System.out.println(field.getModifiers()+"\t"+field.getType()+"\t"+field.getName());
            }
            Method [] methods=c.getDeclaredMethods();
            for(Method m1:methods){
                System.out.println(m1);
                System.out.println(m1.getModifiers()+"\t"+m1.getReturnType()+"\t"+m1.getName());
                Class [] aPara=m1.getParameterTypes();//获取方法的参数也是Class类型
                for(Class cs:aPara){
                    System.out.println(cs.getTypeName());
                }
                Constructor [] constructors=c.getConstructors();
                c.getConstructor();//获取指定的构造方法
            }
    
    
        }
    }
    public class Test3 {
        public static void main(String[] args) throws Exception  {
            Class c= Class.forName("day07.reflect.User");
            //得到无参构造方法的对象
            Constructor con=c.getConstructor(null);
            User user=(User) con.newInstance();
            //动态操作属性
            Field field = c.getDeclaredField("userid");
            field.setAccessible(true);//这个属性不做安全检查,直接访问
            field.set(user,1001);
            System.out.println(field.get(user));
            //动态操作方法
           Method m= c.getDeclaredMethod("setUsername", String.class);
           m.invoke(user,"张三");
            Method m2= c.getDeclaredMethod("getUsername",null);
            System.out.println(m2.invoke(user));
        }
    }
    

     


提高反射效率
反射机制对程序的运行在性能上有一定的影响,速度慢
如何提高反射的性能
1) 通过 setAccessible 提高性能
a) setAccessible 启用和禁用访问安全检查的开关,值为true 则指示反射的对象在使用时应该取消 Java 语言访问检查,值为 false 则指示反射的对象不实施 Java 语言访问检查,并不是为 true 就能访问为 false 就不能访问
b) 禁止安全检查,可以提高反射的运行速度
public class Test01 {
    public static void test01(){
        Object o=new Object();
        long starttime=System.currentTimeMillis();
        for(int i=0;i<1000000000L;i++){
            o.hashCode();
        }
        long endtime=System.currentTimeMillis();
        System.out.println("普通方法执行时间为:"+(endtime-starttime));
    }
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object o=new Object();
        Class c=o.getClass();
        Method method=c.getDeclaredMethod("hashCode",null);
        long starttime=System.currentTimeMillis();
        for(int i=0;i<1000000000L;i++){
            method.invoke(o,null);
        }
        long endtime=System.currentTimeMillis();
        System.out.println("反射方法执行时间为:"+(endtime-starttime));
    }
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        Object o = new Object();
        Class c = o.getClass();
        Method method = c.getDeclaredMethod("hashCode", null);
        method.setAccessible(true);
        long time1 = System.currentTimeMillis();
        for(int i=0;i<1000000000L;i++) {
            method.invoke(o, null);
        }
        long time2=System.currentTimeMillis();
        System.out.println("禁用安全检查反射方法执行时间为:"+(time2-time1));
    }
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test01();
        test02();
        test03();
    }
}

反射操作泛型
 
  1. 泛型
    Java 中的泛型仅仅是给编译器 javac 使用的,确保数据的安全性和免去强制类型转换的麻烦,但是一旦编译完成,所有与泛型有关的类型全部擦除。使用反射直接读取泛型,是读取不到的,因为反射是操作加载以后的类的。
  2. Java 新增的数据类型
    为了通过反射操作这些类型以迎合实际开发的需要
    1) ParameterizedType : 表示一种参数化的类型 , 比 如Collection,可以获取 String 信息
    2) GenericArrayType :泛型数组类型
    3) TypeVariable :各种类型变量的公共父接口
    4) WildcardType :代表一种通配符类型表达式,比如? extends Number,? super Integer(Wildcard 是一个单词,就是通配符 )
    public class Test02 {
        public void test01(Map map,List list,String s){
            System.out.println("test01");
        }
        public Map test02(){
            System.out.println("test02");
            return null;
        }
        public String test03(){
            System.out.println("test03");
            return null;
        }
        public static void main(String[] args) throws NoSuchMethodException {
            //获取test01方法的泛型参数信息
            Class c1=Test02.class;
            Method test01= c1.getMethod("test01",Map.class,List.class,String.class);
            //获取泛型参数的类型
            Type[] types=test01.getGenericParameterTypes();
            System.out.println(types.length);//3
            for(Type type:types){
                //System.out.println("#"+type);
                if(type instanceof ParameterizedType){//只获取带有泛型的参数
                    Type[] g=((ParameterizedType) type).getActualTypeArguments();
                    for(Type t:g){
                        //遍历每一个泛型参数中泛型的类型
                        System.out.println(t);//class java.lang.String  class day07.reflect.User
                    }
                    System.out.println("------------");
                }
            }
            System.out.println("test02方法返回值的泛型信息");
            Method me=c1.getMethod("test02",null);
            Type returnType=me.getGenericReturnType();
            //是否带有泛型
            if(returnType instanceof ParameterizedType){
                //返回值的泛型类型
                Type[] types1=((ParameterizedType) returnType).getActualTypeArguments();
                for(Type t:types1){
                    System.out.println("返回值的泛型类型:"+t);
                }
            }
            System.out.println("test03");
            Method m=c1.getMethod("test03",null);
            Type returnType1 = m.getGenericReturnType();
            System.out.println(returnType1 instanceof ParameterizedType);
        }
    }

     


注解
 
  1. 注解的作用
    1) 不是程序本身,可以对程序作出解释。(这一点跟注释没什么区别)
    2) 可以被其他程序(比如:编译器等)读取。 ( 注解信息处理流程,是注解和注释的重大区别,如果没有注解信息处理流程,则注解毫无意义)
  2. 注解的格式
    1) 注解是以 ”@ 注释名 在代码中存在,还可以添加一些参数值,例如@SuppressWarnings(value=”unchecked”)
  3. 注解在哪里使用
    1) 可以附加在 package,class,method,field 等上面,相当于给它们添加了额外的辅助信息,我们可以通过反射机制编程
    实现对这些元素的访问。
  4. 内置的注解
    1) @Override : 标识方法是重写的方法
    2) @Deprecated :标识的方法不建议使用
    3) @SuppressWarnings :用来抑制编译时的警告信息 @SuppressWarinings 需要提供参数才能正常使用,这些参数都是已经定义好的,我们只需要选择就可以了。

自定义注解
 
  1. 自定义注解的语法
    使 用 @interface 定义自定义注解时,自动继承了 java.lang.annotation.Annotation 接口
    1) @interface 用来声明一个注解
    2) 其中的每一个方法实际上是声明了一个配置参数
    a) 方法的名称就是参数的名称
    b) 返回值类型就是参数类型 ( 返回值类型只能是基本类型、Class String enum)
    c) 可以通过 default 来声明参数的默认值
    d) 如果只有一个成员,一般参数名为 value
    注意事项:注解元素必须要有值。我们定义注解元素时,经常使用空字符串,0 作为默认值。也经常使用负数( 比如 -1) 表示不存在的含义
  2. 元注解
    元注解的作用就是负责注解其他注解。在 Java 中定义了 4个标准的 meta-annotation 类型,它们被用来提供对其它 annotation 类型作说明这些类型和它们所支持的类在 java.lang.annotation 包中可以找到
  3. @Target
    用于描述注解的使用范围 ( 即被描述的注解可以用在什么地方)
    所修饰范围
    取值 ElementType
    package 包 PACKAGE
    PACKAGE
    类、接口、枚举、 Annotation 类型
    TYPE
    类型成员(方法、构造方法、 成员变量、枚举值)
    CONSTRUCTOR: 用于描述构造器
    CONSTRUCTOR: 用于描述构造器
    FIELD: 用于描述域
    METHOD: 用于描述方法
    方法参数和本地变量
    LOCAL_VARIABLE: 用于描述局部变量
    PARAMETER: 用于描述参数
    @Target(value=ElementType.TYPE)
  4. @Retention
    表示需要在什么级别保存该注解信息 , 用于描述注解的生命周期
    取值作用
    SOURCE
    在源文件中有效 ( 即源文件中保留)
    CLASS
    class 文件中有效 ( class保留)
    RUNTIME
    在运行时有效 ( 即运行时保留), 被加载到程序中,可以被反射机制读取
    @Target(ElementType.METHOD)//使用范围在方法上
    @Retention(RetentionPolicy.RUNTIME)//注解的生命周期运行时有效,可以被反射机制读取
    public @interface MyAnnotation {
        //方法的名称就是参数名称,返回值类型就是参数类型,default声明参数的默认值
        String name() default "";
        int age() default 0;
        String[] schoolName() default {"山西大学","太原理工大学"};
    }
    public class Test04 {
        @MyAnnotation(name="weiwei",age=20,schoolName = {"山西大学","太原理工大学"})
        public static void test01(){
        }
    }

     


反射读取注解信息
 
  1. ORM (Object Relationship Mapping)
    1) 类与表结构对应
    2) 属性和字段对应
    3) 对象和记录对应
    使用注解完成类和表结构的映射关系
  2. 功能描述
    Java 中的 Student 类使用第三方程序通过读取注解生成数据库中的表
  3. 实现步骤                                                                                                                                                                                    1) 编写 Student
    2) 编写注解
    3) 在类中使用注解
    4) 通过解析程序将注解读取出来 ( 通过框架解析 )
    5) 拼接 SQL 语句,使用 JDBC 到数据库中执行创建表
  4. @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface sxtTable {
        String value();
    }
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface sxtField {
        String conlumeName();
        String type();
        int length();
    }
    @sxtTable("table_student")
    public class Student {
        @sxtField(conlumeName = "name",type="char",length=10)
        private String name;
        @sxtField(conlumeName = "age",type="int",length=10)
        private int age;
    }
    public class Test05 {
        public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
            Class c=Class.forName("day07.reflect.Student");
            System.out.println("获取类的注解");
            Annotation[] a=c.getDeclaredAnnotations();
            for(Annotation a1:a){
                System.out.println(a1);//@day07.reflect.sxtTable(value=table_student)
            }
            System.out.println("获取指定的注解");
            sxtTable sxtTable =(sxtTable)c.getDeclaredAnnotation(sxtTable.class);
            System.out.println(sxtTable);//@day07.reflect.sxtTable(value=table_student)
            System.out.println("获取属性的注解");
            Field field=c.getDeclaredField("name");
         //   SxtField s =field.getDeclaredAnnotations(SxtField.class);
          //  System.out.println(s);
        }
    }

     

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:使用webpack打包多页面

下一篇:编程小白的毕设开发教程-filter实战

您可能感兴趣

  • 210道面试官必问经典面试题总结分享|Java+JVM+数据库+算法+Spring+中间件+设计模式超详细整理

    “金九银十”的秋招热潮已经来了,由于疫情影响、今年的秋招来的格外早。小编从今天六月份开始备战,不负众望的成功拿下了一些大厂的offer。经过这么多次的面试,凭借自己的面试成功经验和这两个月的准备,小编整理了一份面试清单分享给大家,希望能给和我一样为了秋招奋战多时的码农亲人们一点帮助(java方向),觉得有帮助的同学可以转发点个赞哦~~祝大家面试顺利,一举拿下大厂offer! 一、JAVA基础...

  • 【Python基础】如何编写简洁美观的Python代码

    作者 | ANIRUDDHA BHANDARI 编译 | VK 来源 | Analytics Vidhya 概述 Python风格教程将使你能够编写整洁漂亮的Python代码 在这个风格教程中学习不同的Python约定和Python编程的其他细微差别 介绍 你有没有遇到过一段写得很糟糕的Python代码?我知道你们很多人都会点头的。 编写代码是数据科学家或分析师角色的一部分。另一方面,编写漂...

  • 计算机必备专用英语词汇

    非常好的单词整理,转载一下当作笔记 1.单词说明:   command n. 命令,指令 [kə'mɑ:nd]   单词拼写 名词 单词含义 音标(发音)   提示:着重记忆单词对应的意思,有能力最好词性也记忆。 2.词性说明: n v vi vt conj prep pron adj adv 名词 动词 非及物动词 及物动词 连词 介词 代词 形容词 副词 3.单词列表: 1.file,n...

  • 单日课程超10万节!VIPKID 如何通过实时计算提升上课体验?

    行业解决方案、产品招募中!想赚钱就来传!>>> 摘要:对于以互联网形式的在线教育来说,实时计算应用的场景非常之多,如何通过数据计算来更快、更高效地反馈学习效果保证课程质量是在线教育领域不断探索的主题。本文将从以下四个部分分享,与大家探讨在直播上课过程中如何通过实时计算来提高人效以及系统处理能力。 VIPKID 介绍 核心业务场景 技术实现 总结 Tips: 查看更多最佳实践文章可点击文末链接...

  • 图解一致性哈希算法,全网(小区局域网)最通俗易懂

    好久不见小伙伴们,最近都快忙晕了,后端技术学堂差点停课,不过还是抽时间写了这篇文章带大家一起学习一致性哈希算法。 很多同学应该都知道什么是哈希函数,在后端面试和开发中会遇到「一致性哈希」,那么什么是一致性哈希呢?名字听起来很厉害的样子,其实原理并不复杂,这篇文章带你彻底搞懂一致性哈希! 进入主题前,先来一场紧张刺激的模拟面试吧。 模拟面试 面试官:看你简历上写参与了一个大型项目,用到了分布式...

  • MySQL:互联网公司常用分库分表方案汇总

    点击上方 IT牧场 ,选择 置顶或者星标 技术干货每日送达! 作者:尜尜人物 cnblogs.com/littlecharacter/p/9342129.html 本文目录 一、数据库瓶颈 IO瓶颈 CPU瓶颈 二、分库分表 水平分库 水平分表 垂直分库 垂直分表 三、分库分表工具 四、分库分表步骤 五、分库分表问题 非partition key的查询问题 非partition key跨库跨...

  • 新职业教育的三节课,凭什么做到今天这样

    历时7天、翻遍15个平台渠道、访谈25位参与课程的从业者、挖掘了136条推文的标题和内容,我们得到了12500字的拆解。可以点击右上角☝:收藏、分享、在看,不用担心看一半,找不到文章。 本文信息公开来源:三节课官方公众号、虎嗅网、36氪、深网、东方财富网、新榜、知乎、简书、增长黑盒、短书··· 我们认为,这可能比任何官方复盘更能诠释:「三节课」是如何在3年内,做到互联网职业教育(Almost...

  • 江苏谋定特色小镇-农业大健康·万祥军:旅游理念经营产业

    江苏谋定特色小镇-农业大健康·万祥军:旅游理念经营产业 新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 哲商对话 万赢信采编 :“希望各地会后抓紧时间对培育建设对象进行梳理,根据标准推荐重点对象,有计划、有步骤地组织实施,努力打造富有鲜明个性、成效显著的特色旅游小镇。”特色旅游小镇培育工作座谈会江苏省旅游局局领导詹庚庆表示,江苏省计划通过“十三五”的努力,加...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。