1 Junit

黑盒测试:不需要写代码,给输入值,看程序输出是否符合期望
白盒测试:需要写代码,关注程序具体的执行流程
Junit —> 白盒测试

步骤

  1. 定义一个测试类(测试用例)
    【命名:类名+Test】【包名:xxx.xx.xx.test】
  2. 定义测试方法,可以独立运行
    【命名:test+测试的方法】【返回值:void】【参数列表:空参】
  3. 给方法加注解@Test
  4. 导入Junit的依赖环境

判断结果
5. 断言:Assert.assertEquals(expected,result);
6. 红失败,绿成功

@Before注解,所有测试方法前会先执行,初始化申请资源方法可以用
@After注解,所有测试方法执行后执行,释放资源方法可以用

2 反射

反射:框架设计的灵魂,将类的各个组成成分
框架:半成品软件,可以在框架的基础上进行软件的开发,简化编码

Java代码在计算机中经历的三个阶段
Java文件 —> Javac编译 —>class文件【Source源代码阶段】 —> 类加载器Class.Loader —> Class类对象 【Class类对象阶段】—> 创建对象 —> Xxxx对象 【Runtime运行时阶段】

反射的好处

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

获取字节码Class对象的三种方式

  1. Class.forName(“全类名”):将字节码文件加载进内存,返回class对象
  2. 类型.class:通过类名的属性class获取
  3. 对象.getClass() :getClass()方法在Object类中定义着
    public static void main(String[] args) throws ClassNotFoundException {//1. Class.forName("全类名"):将字节码文件加载进内存,返回class对象Class cls = Class.forName("reflect.Person");System.out.println(cls);//2. 类型.class:通过类名的属性class获取Class cls2 = Person.class;System.out.println(cls2);//3. 对象.getClass() :getClass()方法在Object类中定义着Class cls3 = new Person().getClass();System.out.println(cls3);System.out.println(cls == cls2);//trueSystem.out.println(cls == cls3);//true}

同一个字节码文件**.class文件在一次程序运行中,只会被加载一次,无论通过哪一种方式获取的Class对象都是同一个。

方法1多用于配置文件,将类名定义在配置文件中,读取文件,加载类
方法2多用于参数的传递
方法3多用于对象的获取字节码的方式

class对象的功能

  1. 获取成员变量们
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {Class cls = Person.class;Field[] fields = cls.getFields();//获取所有public修饰的成员变量System.out.println(Arrays.toString(fields));Field school = cls.getField("school");//获取指定的public修饰的成员变量System.out.println(school);Person p = new Person();//获取成员变量school的值Object o = school.get(p);System.out.println(o);//null//设置成员变量school的值school.set(p,"张三小学");System.out.println(p);//Person{name='null', age=0, school='张三小学'}Field[] declaredFields = cls.getDeclaredFields();//获取所有的成员变量for(Field field: declaredFields){System.out.println(field);}//获取私有成员变量的值Field name = cls.getDeclaredField("name");//获取指定的成员变量//访问私有成员前 要忽略访问权限修饰符的安全检查name.setAccessible(true);//暴力反射Object o1 = name.get(p);System.out.println(o1);//null}
  1. 获取构造方法们
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {Class cls = Person.class;//全参构造Constructor constructor = cls.getConstructor(String.class, int.class);System.out.println(constructor);//创建对象Object obj = constructor.newInstance("张三", 19);System.out.println(obj);//空参构造Constructor constructor2 = cls.getConstructor();System.out.println(constructor2);Object obj2 = constructor2.newInstance();System.out.println(obj2);//空参构造一般用这个 简化版Object obj3 = cls.newInstance();System.out.println(obj3);}
  1. 获取成员方方法们
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {Class cls = Person.class;//eat方法为空参Method eat = cls.getMethod("eat");Person p = new Person();//执行方法eat.invoke(p);//eat方法中有一个String类型的参数Method eat2 = cls.getMethod("eat", String.class);eat2.invoke(p," food");//获取所有public修饰的方法Method[] methods = cls.getMethods();for(Method m : methods){System.out.println(m.getName());//除了类自己的方法,Object的方法也存在其中}}
  1. 获取类名

获取的是全类名

    public static void main(String[] args)  {Class cls = Person.class;String name = cls.getName();System.out.println(name);//reflect.Person}

案例:框架类
在不改变该类的任何代码的前提下,可以帮助我们创建任意类的对象并执行任意方法

实现:1. 配置文件 2.反射

步骤:

  1. 将需要创建的对象的全类名和需要执行的方法定义在配置文件中
  2. 在程序中加载读取配置文件
  3. 使用反射技术来加载类文件进内存
  4. 创建对象
  5. 执行方法

创建配置文件 xxx.properties
修改配置文件就可以选择使用的类和方法

className=reflect.Student//全类名
methodName=learn
public class ReflectTest {//在不改变该类的任何代码的前提下,可以帮助我们创建任意类的对象并执行任意方法public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {//1.加载配置文件//1.1创建Properties对象Properties pro = new Properties();//1.2加载配置文件,转换为一个集合//1.2.1获取class目录下的配置文件ClassLoader classLoader = ReflectTest.class.getClassLoader();InputStream is = classLoader.getResourceAsStream("pro.properties");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);}
}

运行执行的是配置文件里对应的类和类的方法

3 注解

定义:Annotation,也叫元数据,一种代码级别的说明,JDK1.5后的新特性,与类、接口、枚举在同一层子,可以声明在包、类、字段、方法、局部变量和方法参数等前面,用来对这些元素进行说明,注释。

概念:JDK1.5之后的新特性,用来说明程序

作用分类

  1. 编译检查:让编译器实现基本的编译检查 【@Override @FunctionalInterface】
  2. 代码分析:通过代码标识的注解对代码进行分析【使用反射】
  3. 编写文档:通过代码表示的注解生产文档【javadoc文档】

JDK的内置注解

  1. @Override:检测被该注解标注的方法是否是继承自父类/父接口的
  2. @Deprecated:将该注解标注的内容,表示已过时
  3. @SuppressWarnings :压制警告 @SuppressWarnings(“all”)写在类上方

自定义注解

  • 格式:
    元注解
    public @interface 注解名称{}

注解的本质:是一个接口 默认继承自Annotation接口
public interface javadoc.MyAnno extends java.lang.annotation.Annotation {}

注解的属性:接口中的抽象方法

要求:

  1. 属性的返回值类型有【基本数据类型 String 枚举 注解 以上类型的数组】,不可以为自定义类和void。
  2. 定义了属性,在使用时需要给属性赋值。如果在定义时,分号前写上default “默认值”,可以不赋值
  3. 如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义。

元注解:用来描述注解的注解

  • @Target:描述注解能够作用的位置
    ElementType的取值:
    TYPE:可以作用于类上
    METHOD:可以作用于方法上
    FILED:可以作用于成员变量上
@Target(value = ElementType.TYPE)
  • @Retention:描述注解被保留的阶段
    RetentionPolicy的取值:
    RUNTIME:当前被描述的注解,会保留到class字节码文件中,并被JVM读取到。
    CLASS:
    SOURCE:
@Retention(RetentionPolicy.RUNTIME)
  • @Documented:描述注解是否被抽取到api文档中
  • @Inherited:描述注解是否被子类继承

解析注解

  1. 获取注解定义的位置对象(Class, Method, Field)
  2. 获取指定的注解:getAnnotation(Class)
    Pro annotation = reflectTestClass.getAnnotation(Pro.class);
  3. 调用注解中的抽象方法来获取配置的属性值

定义注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {String className();String methodName();
}

自定义类

public class Demo01 {public void show(){System.out.println("demo1...show");}
}

定义框架类

@Pro(className = "reflect.Demo01",methodName = "show")
public class ReflectTest {//在不改变该类的任何代码的前提下,可以帮助我们创建任意类的对象并执行任意方法public static void main(String[] args) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {//1.解析注解//1.1 获取该类的字节码文件对象Class<ReflectTest> reflectTestClass = ReflectTest.class;//2.获取注解对象,在内存中生产了一个该注解接口的子类实现对象/*public class ProImpl implements Pro{public String className(){return "reflect.Demo01";}public String methodName(){return "show";}}*/Pro annotation = reflectTestClass.getAnnotation(Pro.class);//3.调用注解对象中定义的抽象方法获取返回值String className = annotation.className();String methodName = annotation.methodName();System.out.println(className);System.out.println(methodName);//4.加载类进内存Class cls = Class.forName(className);//5.创建对象Object obj = cls.newInstance();//6.获取方法对象Method method = cls.getMethod(methodName);method.invoke(obj);}
}

注解案例:简单的测试框架

定义Check注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {}

定义类

package demo;public class Calculator {//加法@Checkpublic void add(){String str = null;str.toString();System.out.println("1 + 0 =" + (1 + 0));}//减法@Checkpublic void sub(){System.out.println("1 - 0 =" + (1 - 0));}//乘法@Checkpublic void mul(){System.out.println("1 * 0 =" + (1 * 0));}//除法@Checkpublic void div(){System.out.println("1 / 0 =" + (1 / 0));}public void show(){System.out.println("no bug...");}
}

测试类-解析程序

public class TestCheck {public static void main(String[] args) throws IOException {//1.创建计算器对象Calculator c = new Calculator();//2.获取字节码文件对象Class cls = c.getClass();//3.获取所有方法Method[] methods = cls.getMethods();BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));//4.判断方法上是否有check注解int num = 0;for(Method method: methods){if(method.isAnnotationPresent(Check.class)){//5.有就执行方法try{method.invoke(c);//6.捕获异常}catch (Exception e){num++;bw.write(method.getName()+"方法出异常了");bw.newLine();bw.write("异常的名称:"+ e.getCause().getClass().getSimpleName());bw.newLine();bw.write("异常的原因:"+e.getCause().getMessage());bw.newLine();bw.write("-----------------------------");bw.newLine();}}}bw.write("本次测试一共出现了"+num+"次异常");bw.flush();bw.close();}
}

bug.txt文件

add方法出异常了
异常的名称:NullPointerException
异常的原因:null
-----------------------------
div方法出异常了
异常的名称:ArithmeticException
异常的原因:/ by zero
-----------------------------
本次测试一共出现了2次异常

4 小结

  1. 大多数时候,我们会使用注解,而不是自定义注解
  2. 注解是给编译器和解析程序用的
  3. 注解不是程序的一部分

【Java】Junit、反射和注解的笔记相关推荐

  1. Java 使用反射处理注解

    Java 使用反射处理注解 自定义注解的格式: [public|final] @interface 注解名//@interface 表明:这是一个自定义注解 {注解元素//注解元素 是无参数的方法 } ...

  2. java 中的 Annotation 注解学习笔记

    java 中的 Annotation 注解 什么是注解 元注解 @Target @Retention @Document @Inherited 自定义注解 什么是注解 Annotation 是从JDK ...

  3. Java:反射和注解从入门到放弃

    以下是两个讲得通俗易懂的注解与反射例子,敬请参考! 注解: 秒懂,Java 注解 (Annotation)你可以这样学 反射: Java反射:框架设计的灵魂

  4. java Junit 为什么@Test注解里的方法必须是public void修饰的

    通过查阅了Junit的源码,里面有段代码是这样的 1 protected void validateInstanceMethods(List < Throwable > errors) { ...

  5. 七、Web服务器——Junit单元测试 反射 注解学习笔记

    今日内容 1. Junit单元测试 2. 反射 3. 注解 Junit单元测试: * 测试分类:1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值.2. 白盒测试:需要写代码的.关注程 ...

  6. 黑马就业班(01.JavaSE Java语言基础-11.Java基础加强)——基础加强:Junit单元测试、反射、注解

       1.Junit单元测试 测试分类: 1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值. 2. 白盒测试:需要写代码的.关注程序具体的执行流程. Junit使用:白盒测试 步骤: ...

  7. Java中如何创建自定义的注解学习笔记(MD版)

    概要 Java中如何创建自定义的注解学习笔记(MD版). 博客 博客地址:IT老兵驿站. 前言 记得这篇笔记还是在泉州的龙玲酒店记录的,是一个周六的晚上,坐飞机从上海到泉州,从笔记中能勾起一些旅游的回 ...

  8. java自定义注解学习笔记

    注解学习笔记之自定义注解 @Target({1,2,3,4,5,6,7}) 1.ElementType.CONSTRUCTOR:用于描述构造器 2.ElementType.FIELD:用于描述域 3. ...

  9. junit单元测试,反射,注解

    今日内容 1. Junit单元测试 2. 反射 3. 注解 Junit单元测试: * 测试分类:1. 黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值.2. 白盒测试:需要写代码的.关注程 ...

最新文章

  1. eclipse配置springboot开发
  2. mysql root情况
  3. kettle的基本介绍
  4. 构建之法阅读心得(二)
  5. TCP 和 UDP 绑定同一端口通信的解释
  6. html5包含哪些知识,HTML5新知识
  7. jquery 分页插件
  8. Windows7 64bit oracle 11g plsql错误 Initialhation orrlr SQK*NET properly installed
  9. 荷兰国旗问题+快速排序
  10. IntelliJ IDEA快速入门 | 第九篇:IntelliJ IDEA中的常用配置(一)——设置IntelliJ IDEA的主题
  11. 仓央嘉措---不负如来不负卿---问佛--见与不见
  12. 基于线性函数近似的安全强化学习 Safe RL with Linear Function Approximation 翻译 1
  13. Civilization V and Beyond Earth
  14. 微信添加地址时选择地区功能是怎么实现的
  15. 【项目】智能WiFi远程灯光控制系统
  16. 实验一:inode耗尽导致磁盘故障
  17. MySQL之MVCC原理
  18. Java基础之JDK 8下载、安装和环境变量配置
  19. 16各种设计LOGO标准尺寸
  20. egg-sequelize使用教程

热门文章

  1. Android wakelock 自上而下浅析
  2. MFC CStringArray 字符串数组类 使用方法
  3. Python学习——常见的字符串匹配
  4. java 检索ldap,从LDAP(Java)检索信息
  5. opencv 二值化_Python-OpenCV获取图像轮廓的图像处理方法
  6. html5+css3第一次作业_“台风爷爷,让我作业飞走!”南京小学生写的诗都这么逆天了?...
  7. javascript犀牛书_犀牛书作者:最该忘记的JavaScript特性
  8. 【Pytorch神经网络实战案例】07 预测泰坦尼克号上生存的乘客
  9. php中get_featured_posts()是什么意思,WordPress的Get_Posts()函数详解
  10. 一、数据预处理——数据归一化 数据标准化