注解于单元测试和日志技术简单介绍
注解
注解的概述:
注解就是对程序进行标注和解释
例如:@Override 描述子类重写父类方法
@Deprecated 描述方法过时
@SuppressWarnings 压制警告
代码:
public class Fu {
public void show(){
System.out.println("这是Override注解");
}
}
public class Zi extends Fu{
@Override//告诉我们编译器这个方法是重写了父类的show方法
//那么我们在进行方法定义的时候,就需要重写方法的要求进行方法定义
public void show() {
System.out.println("子类的方法");
}
//这是一个过时的方法
@Deprecated
public void method(){
System.out.println("过时的方法注解。。。");
}
@SuppressWarnings(value = "all")
//表示压制方法中所有的警告
//比如a,b的值没有用到,定义完了是灰色的 写下这个注解就可压制住
//如果是写在类上边,就压制类中所有的警告
public void method1(){
int a=10;
int b=20;
}
}
注解和注释的区别:
注释:是给我们写程序的人看的
注解:是给编译器看的(让虚拟机看到程序的注解,注解代表程序的一些特殊功能)
自定义注解---格式
public @interface 注解名称{
public 属性类型 属性名 ()default默认值;
}
属性类型:基本数据类型,String,Class,注解,枚举,以上类型的一维数组
枚举类:
public enum Season {
Spring,Summer,Autumn,Winter;
}
自定义Test类
public @interface Test {
}
自定义注解类
public @interface Method {
//定义一个基本数据类型的属性
int a () default 30;
//定义一个String类型的属性
public String Name();
//定义一个class类型的属性
public Class clazz() default Test.class;
//定义一个注解类型的属性
public Test test() ;
//定义一个枚举类型的属性
public Season season() default Season.Spring;
//以上类型的一维数组
//int l类型的数组
public int[] arr() default {1,2,3,4,5};
//枚举类型数组
public Season[] seasonArr() default {Season.Spring,Season.Autumn,Season.Summer,Season.Winter};
}
测试类
//在使用注解的时候,如果注解里面的属性没有指定默认值
//那么我们需要手动给出注解属性的设置值
@Method(name = "zhangsan")
public class Demo {
public static void main(String[] args) {
}
}
特殊的属性value 特殊的属性value 后期如果我们只需要给注解的value属性赋值
自定义注解类
public @interface Method {
//定义一个基本数据类型的属性
int a () default 30;
//定义一个String类型的属性
public String name() default "zhangsan";
//定义一个class类型的属性
public Class clazz() default Test.class;
//定义一个注解类型的属性
public Test test() default @Test;
//定义一个枚举类型的属性
public Season season() default Season.Spring;
//以上类型的一维数组
//int l类型的数组
public int[] arr() default {1,2,3,4,5};
//枚举类型数组
public Season[] seasonArr() default {Season.Spring,Season.Autumn,Season.Summer,Season.Winter};
//特殊的属性value 后期如果我们只需要给注解的value属性赋值
public String value();
}
测试类
//在使用注解的时候,如果注解里面的属性没有指定默认值
//那么我们需要手动给出注解属性的设置值
//@Method(name = "zhangsan")
@Method("abc")
public class Demo {
public static void main(String[] args) {
}
}
元注解:就是描述注解的注解
@Target 指定了注解能在哪里使用
@Retention 可以理解为保留时间(生命周期)
@Inherited 表示修饰的自定义注解可以被子类继承
@Documented 表示该自定义注解,会出现在API文档里
演示继承关系
子类
public class Zi {
public void show(){
System.out.println("这是子类的show方法");
}
}
父类
@Anno
public class Fu {
}
自定义测试类
@Target({ElementType.FIELD,ElementType.TYPE,ElementType.METHOD}) //指定了注解使用的位置 (成员变量 类 方法)
@Retention(RetentionPolicy.RUNTIME)//指定了该注解的存活时间 如果不指定就会只存在class文件运行阶段
@Inherited //指定该注解可以被继承
public @interface Anno {
}
测试类
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
//获取到zi类中的字节码文件对象
Class aClass = Class.forName("com/sx/test2/Zi.java");
//获得注解
boolean present = aClass.isAnnotationPresent(Anno.class);
System.out.println(present);//true
}
}
单元测试
JUnit简介:JUnit是Java语言的单元测试工具,JUnit是一个非常重要的测试工具
Junit是一个开放源代码的测试工具
提供注解来识别测试方法
Junit测试可以让你编写的代码更快,并能提高质量
JUnit优雅简洁,没那么复杂,花费时间较少
JUnit在一个条中显示进度,如果运行良好则是绿色,如果运行失败,则变成红色
单元测试使用
1.将junit的jar包导入到工程中
2.编写测试方法,该测试方法必须是公共的无参数无返回值的非静态方法
3.在测试方法上使用@Test注解标注该方法是一个测试方法
4.选中测试方法右键执行
当前模块下 新建一个文件夹lib jar粘贴进去 右键点击 Add as libary 表示jar包已经导入进去
下载地址:juint-4.10(https://sourceforge.net/projects/junit/)
提示:如果是4.11版本以上的话需要加上hamcrest-core-1.3.jar 还有一种办法就是使用低版本
代码:
public class Test {
public static void main(String[] args) {
}
//main方法中并没有运行add方法test
@org.junit.Test
public void add(){
System.out.println(2/0);
int a=10;
int b=20;
int sun=a+b;
System.out.println(sun);
}
}
常用注解:
@Test 表示测试该方法
@Before 在测试的方法前运行
@After 在测试的方法后运行
代码
public class Test {
@After
public void after(){
System.out.println("这是after方法");
}
@Before
public void before(){
System.out.println("这是before方法");
}
@org.junit.Test
public void test(){
System.out.println("这是test方法");
}
}
注意 after方式第一个before第二个 Test第三个
日志技术
在前面我们都是在代码的中间插入输出语句 来体现代码的进度
弊端:想取消记录的信息需要修改代码才可以完成
信息只能展示在控制台,不能将其记录到其他的位置(文件,数据库)
日志技术:程序中的日志可以用来记录程序在运行的时候的点点滴滴,并可以永久存储
总结:取消日志 输出语句需要修改代码,不具有灵活性,输出位置也只能是控制台,和业务代码处于一个线程中
而日志技术不朽要修改代码,具有灵活性,可以将日志信息写入到文件或者数据库中 多线程方式记录入职,不影响业务代码的性能
日志技术的体系结构和Log4g
Log4j是Apache的一个开源项目,通过Log4j,我们可以控制日志信息输送的目的地是控制台,文件等位置,
也可以控制每一条日志的输出格式
通过每一条日志信息的级别,我们能更细致地控制日志的生产过程,可以通过配置文件来灵活的配置,不需要修改相应的代码
Log4j的开发流程
1.导入log4j的相关jar包
2.编写log4j的配置文件
log4j.rootLogger=info,my,fileAppender
### direct log messages to my ###
log4j.appender.my=org.apache.log4j.ConsoleAppender
log4j.appender.my.ImmediateFlush = true
log4j.appender.my.Target=System.out
log4j.appender.my.layout=org.apache.log4j.PatternLayout
log4j.appender.my.layout.ConversionPattern=%d %t %5p %c{1}:%L - %m%n
# fileAppender��ʾ
log4j.appender.fileAppender=org.apache.log4j.FileAppender
log4j.appender.fileAppender.ImmediateFlush = true
log4j.appender.fileAppender.Append=true
log4j.appender.fileAppender.File=D:/log4j-log.log
log4j.appender.fileAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.fileAppender.layout.ConversionPattern=%d %5p %c{1}:%L - %m%n
3.在代码中获取日志的对象
4.按照级别设置记录日志信息代码:
public class tes {
//使用log4j的api来获取日志的对象
//弊端:如果以后更换日志的实现类,下边的代码需要跟着改
//private static final Logger LOGGER= (Logger) org.apache.log4j.Logger.getLogger(tes.class);
// 使用slf4j里面的api来获取日志的对象
// 好处:如果我们以后更换日志,代码不需要用
private static final Logger LOGGER= LoggerFactory.getLogger(tes.class);
public static void main(String[] args) {
LOGGER.debug("debug级别的日志");
LOGGER.info("info级别的日志");
LOGGER.info("warn级别的日志");
LOGGER.info("error级别的日志");
//2022-04-26 01:56:02,501 main DEBUG tes:17 - debug级别的日志
//2022-04-26 01:55:27,052 main INFO tes:18 - info级别的日志
//2022-04-26 01:55:27,056 main INFO tes:19 - warn级别的日志
//2022-04-26 01:55:27,061 main INFO tes:20 - error级别的日志
}
}
LOG4J的三个核心
Loggers(记录器) 日志的级别
Appenders(输出源) 日志要输出的地方
Layouts(布局) 日志输出的格式
Loggers(记录器) 日志的级别
Loggers组件在此系统中最常见的五个级别:DEBUG,INFO,WARN,ERROR,和FATAL
DEBUG:基本信息 INFO:重要信息 WARN:可能出现的问题 给程序员一些提示 ERROR:错误信息但不影响程序运行 FATAL:重大错误 致使程序运行不下去
Log4j有一个规则:只输出级别不低于设定级别的日志信息
Appenders(输出源)
把日志输出到不同的地方,如控制台(Console) ,文件(Files)等
Layouts(布局)
根据自己的喜好规定日志输出的格式