Java笔记(14)-反射与注解

  1. Junit单元测试
1. Junit白盒测试
2. 使用步骤:
    a. 定义一个测试类(测试用例)
        建议:测试类名:被测试类名+Test -- CaculatorTest
              包名:xxx.xxx.xx.test
    b. 定义测试方法:可以独立运行
        建议:
            方法名:test+测试的方法名 -- testAdd()
            返回值:void
            参数列表:空参
    c. 给方法加上注解@Test
    d. 导入junit依赖包
3. 判定结果:
    不看程序输出,而使用断言Assert操作来处理结果
    判定期望是否与程序结果一致
4. 当测试带有IO操作的程序时,时常需要申请资源,释放资源
    建议:
        定义个init()方法,用于所有测试的资源申请
        在init()方法前加注解@Before
        定义个close()方法,用于所有测试的资源释放
        在close()方法前加注解@After -- 即使测试时抛出异常,close方法仍然会执行
  1. 反射
1. 反射是框架设计的灵魂
    -- 框架:半成品软件。可以在框架的基础上进行软件开发
    -- 反射:将类的各个组成部分封装为其他对象。
2. Java程序执行的三个阶段:
    1. Source源代码阶段:由源代码 --> class字节码
    2. 通过类加载器ClassLoader加载class文件
    3. Class类对象阶段:
        由class文件 --> Class类对象{
            成员变量:Field[] fields
            构造方法:Constructor[] cons
            成员方法:Method[] methods
        }
    3. Runtime阶段:创建对象加载到内存中
3. 将成员变量封装为Field对象,将构造方法封装为Constructor对象,将成员方法封装为Method对象,这就指的是反射。
4. 作用:
    1. 可以在程序的运行过程中操作这些对象 -- 代码提示
    2. 可以解耦,提高程序可扩展性
  1. 获取Class对象
1. 在第一个阶段时:
    Class.forName("全类名<包路径+'.'+类名>");//将字节码文件加载仅内存,返回Class对象
    多用于配置文件,将类名定义在配置文件中。读取文件加载类
2. 在第二个阶段:
    类名.class;//导入类定义文件后,通过类名的属性class来获取
    多用于参数的传递
3. 在第三个阶段:
    对象.getClass();//创建对象后,通过Object类中定义的成员方法返回其Class对象
    多用于对象的方式获取字节码对象
  1. 使用Class对象
1. 获取功能:
    a. 获取成员变量
        1. Field[] getFields() //只能获取所有public修饰的成员变量
		2. Field getField(String name)  //只能获取指定名称的public修饰的成员变量

		3. Field[] getDeclaredFields()  获取所有的成员变量,不考虑修饰符
		4. Field getDeclaredField(String name)
    b. 获取构造方法们
		1. Constructor<?>[] getConstructors()  
		2. Constructor<T> getConstructor(<?>... parameterTypes)  

		3. Constructor<T> getDeclaredConstructor(<?>... parameterTypes)  
		4. Constructor<?>[] getDeclaredConstructors() 
    c. 获取成员方法们:
		1. Method[] getMethods()  
		2. Method getMethod(String name,<?>... parameterTypes)  

		3. Method[] getDeclaredMethods()  
		4. Method getDeclaredMethod(String name,<?>... parameterTypes)  

    d. 获取全类名	
		1. String getName()
		2. String getPackage()
2. Field对象成员方法:
    a. 获取成员变量的值
        1. Field f = personClass.getFeild("变量名<a>");
        2. Person p = new Person();
        3. Object value = f.get(p);//获取p对象中的成员变量a的值
    b. 设置成员变量值
        4. f.set(对象名, 成员变量a要设置的值);//给指定对象的成员变量a设置值
3. 暴力反射
    由于getDeclaredField成员方法可以获取私有成员变量
    但是,直接对私有成员变量使用get/set方法时,会抛出异常,提示非法权限
    因此,需要忽略权限设置,使用成员方法setAccessible忽略
    f.setAccessible(true);
    对于成员方法和构造方法对象中同样有该成员方法
4. Constructor对象成员方法:
    a. 创建对象:
        T newInstance(Object ... initargs);//参数传构造对象的参数,如果获取到的是有参构造则传正确参数
        例如:
            Constructor cons = personClass.getConstructor(String.class, int.class);//获取指定参数列表的构造函数
            Object p = cons.newInstance("nameXXX",12);//通过传入参数创建对象
5. Method对象成员方法:
    a. 执行方法:
        Object invoke(Object obj, Object... args);//使用指定对象obj执行该方法,且方法的参数为参数列表args
                                                  //空参方法直接传入obj即可
        例如:
            Method eat = personClass.getMethod("eat");
            Person p = new Person();
            eat.invoke(p);//空参的eat方法
            Method eat2 = personClass.getMethod("eat", String.class);
            eat2.invoke(p,"args");//带参数的eat方法
    b. 获取方法名称:
        String getName()
        例如:
            eat.getName();//返回"eat"
  1. 实现一个小框架
1. 实现步骤:配置文件 --> 反射
    a. 将需要创建类型的全类名和需要执行的方法定义在一个配置文件中
    b. 在程序中加载读取配置文件
    c. 利用反射技术加载类文件进内存
    d. 创建类对象
    e. 执行方法
2. 例如:
    psvm{
        //1. 加载配置文件
        //1.1 创建Properties对象
        Properties pro = new Properties();
        //1.2 加载配置文件,转换为集合
        //1.2.1 首先获取本文件的类加载器
        ClassLoader cld = ReflectTest.class.getClassLoader();
        //1.2.2 由本文件的类加载器可以加载该类的目录下的文件,因此由该类加载器来加载配置文件
        //加载文件后返回该文件的字节流
        InputStream is = cld.getResourceAsStream("pro.properties");
        //1.3 加载配置文件
        pro.load(is);

        //2. 获取配置文件中的数据
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3. 加载该类进内存
        Class cls = Class.forName(className);
        //4. 创建对象
        Object obj = cls.newInstance();
        //5. 获取方法对象
        Method method = cls.getMethod(methodName);
        //6. 执行方法
        method.invoke(obj);
    }
    配置文件pro.properties
    className=xx.xx.Person
    methodName=eat
  1. 注解
1. JDK 1.5+一种代码级别的说明。声明在包,类,字段,方法,局部变量,方法参数等前面,用来说明
2. 作用:
    编写文档:通过代码内标识的注解生成文档<API文档> -- 使用javadoc命令
    代码分析:通过注解对代码进行分析 -- 使用反射抽取注解
    编译检查:例如<@Override>
3. 预定义注解:
    @Override:检测被该注解标注的方法是否继承自父类
    @Deprecated:该注解标注的内容表示已经过时 -- 用于兼容低版本
    @SuppressWarnings:压制警告 -- @SuppressWarnings("all")压制所有警告
4. 自定义注解:
    a. 格式:
        元注解
        public @interface 自定义注解名{
        }
    b. 本质:
        注解本质上是一个接口
        pubic interface 注解名 extends Annotation {}
    c. 属性:注解中的成员变量和方法
        1. 属性的返回值类型:
            基本数据类型/String/枚举/注解/以上类型的数组
        2. 定义了属性后,在使用时需要给属性赋值 
            -- 也可以在定义时标注默认值,使用default关键字
            -- String name() default "testName";
            -- 如果只有一个属性需要复制,且属性名为value,则在使用时可以不标注属性名
                public @interface SuppressWarnings{
                    String[] value();
                }
                在使用时直接标注@SuppressWarnings("all")
                完整为@SuppressWarnings(value = "all")
                多个值的使用逗号分隔
    d. 元注解:用于描述注解的注解
        @Target:描述注解能够作用的位置
            ElementType取值:
                TYPE:表示可以作用于类上
                METHOD:表示可以作用与方法上
                FIELD:表示可以作用与成员变量上
        @Retention:描述注解被保留的阶段 -- Java代码的三个阶段
            RetentionPolicy取值:
                SOURCE:表示注解不会保留到class字节码中
                CLASS:表示注解会保留到class字节码文件中,不会被JVM读取
                RUNTIME:表示注解会保留到class字节码文件中,并被JVM读取
        @Documented:描述注解是否被抽取到API文档中
        @Inherited:描述该注解是否被子类继承
5. 获取注解属性的值
    a. 获取注解定义位置的对象 -- 即Class,Method,Field对象,它们中都有成员方法getAnnotation
    b. 通过对象成员方法getAnnotation获取指定注解对象
    c. 通过注解对象调用成员方法获取属性值
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值