• java进阶知识--反射、junit、注解


    一、反射

     1.1 反射机制

        概述:将类的各个组成部分封装成其他对象,在代码运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

        好处:

          1. 可以在程序运行的过程中,操作这些对象;
          2. 可以解耦,提高程序的可扩展性。

        用途:在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

        反射机制的相关类:

    类名用途
    Class类 代表类的实体,在运行的Java应用程序中表示类和接口
    Field类 代表类的成员变量(成员变量也称为类的属性)
    Method类 代表类的方法
    Constructor类 代表类的构造方法
        java代码在计算机中经历的三个阶段

     1.2 获取Class对象的方式

         1. Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
            * 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
         2. 类名.class:通过类名的属性class获取
            * 多用于参数的传递
         3. 对象.getClass():getClass()方法在Object类中定义着。
            * 多用于对象的获取字节码的方式
         结论:
         同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。
      小贴士:
        上述三种获取Class对象的方式,刚好对应java代码经历的三个阶段。

     1.3 Class对象功能

        获取功能:
          1. 获取成员变量
             * Field[] getFields() :获取所有public修饰的成员变量
             * Field getField(String name)   获取指定名称的 public修饰的成员变量
     
             * Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
             * Field getDeclaredField(String name)  获取指定名称的成员变量,不考虑修饰符
          2. 获取构造方法
             * Constructor<?>[] getConstructors() 
             * Constructor<T> getConstructor(类<?>... parameterTypes) 
     
             * Constructor<?>[] getDeclaredConstructors() 
             * Constructor<T> getDeclaredConstructor(类<?>... parameterTypes) 
          3. 获取成员方法
             * Method[] getMethods() 
             * Method getMethod(String name, 类<?>... parameterTypes) 
     
             * Method[] getDeclaredMethods() 
             * Method getDeclaredMethod(String name, 类<?>... parameterTypes) 
          4. 获取全类名 
             * String getName()  

     1.4 Field成员变量

        操作:
          1. 设置值
             * void set(Object obj, Object value) 
          2. 获取值
             * get(Object obj)
          3. 当给私有属性get/set时,需忽略访问权限修饰符的安全检查
             * setAccessible(true):暴力反射

     1.5 Constructor构造方法

        创建对象:
          * T newInstance(Object... initargs)

      如果使用空参数构造方法创建对象时,操作可以简化:Class对象.newInstance方法

     1.6 Method方法对象

        * 执行方法:
          * Object invoke(Object obj, Object... args)
        * 获取方法名称:
          * String getName:获取方法名
     

    二、Junit单元测试

     2.1 测试分类

        1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。
        2. 白盒测试:需要写代码的。关注程序具体的执行流程。

     2.2 Junit使用(白盒测试的一种)

         步骤:
          1. 定义一个测试类(测试用例)
              * 测试类名:被测试的类名Test
              * 包名:xxx.xxx.xx.test
          2. 定义测试方法:可以独立运行
              * 方法名:test测试的方法名  testAdd() 
              * 返回值:void
              * 参数列表:空参
          3. 给方法加@Test
          4. 导入junit依赖环境
          * 判定结果:
            * 一般我们会使用断言操作来处理结果:Assert.assertEquals('期望的结果','运算的结果');
     补充:
        * @Before注解:  修饰的方法会在测试方法之前自动被执行
        * @After注解:  修饰的方法会在测试方法执行之后自动被执行
     

    三、注解

     3.1 概述

        注解(Annotation),也叫元数据。一种代码级别的说明,即用来说明程序的。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。
    小贴士:它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
        格式:@注解名称

     3.2 注解的作用

        分类:
          ①编写文档:通过代码里标识的注解生成文档【生成文档doc文档】
          ②代码分析:通过代码里标识的注解对代码进行分析【使用反射】
          ③编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查【Override】

     3.3 JDK中预定义的一些注解

        * @Override :检测被该注解标注的方法是否是继承自父类(接口)的
        * @Deprecated:该注解标注的内容,表示已过时
        * @SuppressWarnings:压制警告
            * 一般传递参数all  @SuppressWarnings("all")

     3.4 自定义注解

       3.4.1 格式

          元注解
          public @interface 注解名称{
            属性列表;
          }

       3.4.2 本质

          注解本质上就是一个接口,该接口默认继承Annotation接口。

          如:public interface MyAnno extends java.lang.annotation.Annotation {...}

       3.4.3 属性 

          属性:接口中的抽象方法
            * 要求:
               1. 属性的返回值类型有下列取值
                  * 基本数据类型
                  * String
                  * 枚举
                  * 注解
                  * 以上类型的数组
               2. 定义了属性,在使用时需要给属性赋值
                  * 如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值。
                  * 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。
                  * 数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略

       3.4.4 元注解

          元注解:用于描述注解的注解
            * @Target:描述注解能够作用的位置
               * ElementType取值:
                  * TYPE:可以作用于类上
                  * METHOD:可以作用于方法上
                  * FIELD:可以作用于成员变量上
            * @Retention:描述注解被保留的阶段
                * RetentionPolicy取值:
                *CLASS:编译器将把注释记录在类文件中,但在运行时 VM 不需要保留注释。
                * RUNTIME:编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
                * SOURCE:被修饰的注解只能存在源码中,字节码class没有。编译器要丢弃的注释。

            * @Documented:描述注解是否被抽取到api文档中
            * @Inherited:描述注解是否被子类继承



     面试题:描述一下JVM加载class文件的原理机制?

      JVM中类的装载是由ClassLoader和它的子类来实现的。
      Java ClassLoader是一个重要的Java运行时系统组件,它负责在运行时查找和装入类文件的类。

  • 相关阅读:
    IIS配置跨域请求
    ABP框架页面权限验证
    WPF-DataGrid增删改查不绑定数据源
    WPF-DataGrid增删改查绑定数据源
    .NET开发框架集合(长期更新)
    C# Webbrowser 常用方法及多线程调用
    Devexpress-GridLookUpEdit
    Devexpress提示框的使用
    Asp.Net MVC中Action跳转小结
    ASP.NET MVC备忘
  • 原文地址:https://www.cnblogs.com/sun9/p/13570345.html
Copyright © 2020-2023  润新知