您现在的位置是:首页 >技术杂谈 >面向对象(高级)-Annotation注解、单元测试的使用网站首页技术杂谈

面向对象(高级)-Annotation注解、单元测试的使用

冰默不准偷懒 2023-05-19 20:00:02
简介面向对象(高级)-Annotation注解、单元测试的使用

注解(Annotation)

注解大纲

注解的使用

1.Annotation的理解
- 注解(Annotation)是从'JDK5.0'开始引入,以'@注解名'在代码中存在。
- Annotation可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明。
  还可以添加一些参数值,这些信息被保存在Annotation"name = value"对中。
- 注解可以在类编译、运行时进行加载,体现不同的功能。

2.注解的应用场景:
示例1:生成文档相关的注解
示例2:在编译时进行格式检查(JDK内置的三个基本注解)
示例3:跟踪代码依赖性,实现替代配置文件功能


3.JAVA基础涉及到的三个常用的注解
@Override:限定重写父类方法,该注解只能用于方法
@Deprecated:用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择
@SuppressWarnings:抑制编译器警告   IDEA代码右边滚动条底下黄色的小横杠就是各种警告信息,如没使用这个变量,方法过时等,
    如何取消小黄杠?
    鼠标指针放在小黄杠上,点击右下角的More Actions...(更多操作...)——点击黄色小灯泡最右边的向右三角形,选择Suppress...小黄杠就没了


4.自定义注解
以@SuppressWarnings为参照,进行定义即可。

5.元注解的理解:
元注解:对现有的注解进行解释说明的注解。

讲4个元注解:
(1. @Target:用于描述注解的使用范围
- 可以通过枚举类型ElementType10个常量对象来指定
- TYPE,METHOD,CONSTRUCTOR,PACKAGE......2. @Retention:用于描述注解的生命周期
- 可以通过枚举类型RetentionPolicy3个常量对象来指定
- SOURCE(源代码)、CLASS(字节码)、RUNTIME(运行时)
- 唯有RUNTIME阶段才能被反射读取到。

(3. @Documented:表明这个注解应该被Javadoc工具记录。
(4. @Inherited:允许子类继承父类中的注解



拓展:元数据。
String name = "冰默";
String name是冰默的元数据

框架 = 注解 + 反射 + 设计模式
  • 什么是注解

    注解(Annotation)是从JDK5.0开始引入,以**@注解名**在代码中存在。例如:

@Override	//重写
@Deprecated		//表示相应的一些结构过时了
@SuppressWarnings(value = "unchecked")		//抑制编译器警告

​ Annotation可以像修饰符一样被使用,可用于修饰包、类、构造器、方法、成员变量、参数、局部变量的声明。还可以添加一些参数值,这些信息被保存在Annotation的"name = value"对中。

​ 注解可以在类编译、运行时进行加载,体现不同的功能。

  • 注解与注释

    注解也可以看做是一种注释,通过使用Annotation,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。但是,注解,不同于单行注释和多行注释。

    • 对于单行注释和多行注释是给程序员看的。
    • 而注解是可以被编译器或其他程序读取的。程序还可以根据注解的不同,多出相应的处理。
  • 注解的重要性

在JavaSE中,注解的使用目的比较简单,例如标记过时的功能,忽略警告等。在JavaEE/Android中注解占据了更重要的角色,例如用来配置应用程序的任何切面,代替JavaEE旧版中所遗留的繁冗代码XML配置等。

未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernate3.x以后也是基于注解的,Struts2有一部分也是基于注解的了。注解是一种趋势,一定程度上可以说:框架 = 注解 + 反射 + 设计模式

常见的Annotation作用

示例1:生成文档相关的注解

@author 标明开发该类模块的作者,多个作者之间使用,分割
@version 标明该类模块的版本
@see 参考转向,也就是相关主题
@since 从哪个版本开始增加的
@param 对方法中某参数的说明,如果没有参数就不能写
@return 对方法返回值的说明,如果方法的返回值类型是void就不能写
@exception 对方法可能抛出的异常进行说明,如果方法没有用throws显示抛出的异常就不能写

示例2:在编译时进行格式检查(JDK内置的三个基本注解)

@Override:限定重写父类方法,该注解只能用于方法

@Deprecated:用于表示所修饰的元素(类,方法等)已过时。通常是因为所修饰的结构危险或存在更好的选择

@SuppressWarnings:抑制编译器警告

示例3:跟踪代码依赖性,实现替代配置文件功能

  • Servlet3.0提供了注解(annotation),使得不再需要在web.xml文件中进行Servlet的部署。

三个最基本的注解

  • @Override

    • 用于检测被标记的方法为有效的重写方法,如果不是,则报编译错误!
    • 只能标记在方法上。
    • 它会被编译器程序读取。
  • @Deprecated

    • 用于表示被标记的数据已经过时,不推荐使用。
    • 可以用于修饰属性,方法,构造,类,包,局部变量,参数。
    • 他会被编译器程序读取。
  • @SuppressWarnings

    • 抑制编译警告。当我们不希望看到警告信息的时候,可以使用SuppressWarnings注解来抑制警告信息。
    • 可以用于修饰类、属性、方法、构造、局部变量、参数。
    • 他会被编译器程序读取。
    • 可以指定的警告类型有(了解)
    1. all,抑制所有警告
    2. unchecked,抑制与未检查的作业相关的警告
    3. unused,抑制与未用的程式码及停用的程式码相关的警告
    4. deprecation,抑制与淘汰的相关警告
    5. nls,抑制与非nls字串文字相关的警告
    6. null,抑制与空值分析相关的警告
    7. rawtypes,抑制与使用raw类型相关的警告
    8. static -access,抑制与静态存取不正确相关的警告
    9. static- method,抑制与可能宣告为static的方法相关的警告
    10. super,抑制与置换方法相关但不含super呼叫的警告

元注解

JDK1.5在java.long.annotation包定义了4个标准的meat-annotation类型,它们被用来提供对其他annotation类型作说明。

  1. **@Target:**用于描述注解的使用范围
  • 可以通过枚举类型ElementType的10个常量对象来指定
  • TYPE,METHOD,CONSTRUCTOR,PACKAGE…
  1. **@Retention:**用于描述注解的生命周期
  • 可以通过枚举类型RetentionPolicy的3个常量对象来指定
  • SOURCE(源代码)、CLASS(字节码)、RUNTIME(运行时)
  • 唯有RUNTIME阶段才能被反射读取到
  1. @Documented:表明这个注解应该被Javadoc工具记录。

  2. @Inherited:允许子类继承父类中的注解


package oop.demo15_annotation;

import java.util.Date;

public class AnnotationTest {
    public static void main(String[] args) {
        //new Student().walk();
        Person p1 = new Student();
        p1.walk();//学生走路

        Date date = new Date();
        System.out.println(date);

        Date date1 = new Date(2023,4,11);//这是一个过时的方法,所以这个Date中间有条删除线,不推荐用,但是可以使用
        System.out.println(date1);//输出3923,这个过时的方法要减去1900,才能是2023

        Person p2 = new Person();
        @SuppressWarnings({"deprecation"}) Person p3 = new Person("小明");
        System.out.println(p3);

        @SuppressWarnings("unused") int num = 10;
    }
}

@MyAnnotation(value = "class")
class Person{
    String name;
    int age;

    @MyAnnotation()//没写,默认就是Hello
    //无参构造器
    public Person() {
    }

    //有参构造器
    @Deprecated //有了Deprecated说明以下方法为过时,上面用到这个方法的时候,这个方法名就有删除线
    public Person(String name) {
        this.name = name;
    }

    public void eat(){
        System.out.println("人干饭");
    }

    public void walk(){
        System.out.println("人走路");
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + ''' +
                ", age=" + age +
                '}';
    }
}

class Student extends Person{

    @Override//注意Override只能够用来修饰方法
    public void eat() {
        System.out.println("学生干饭");
    }

    @Override
    public void walk(){
        System.out.println("学生走路");
    }
}

自定义注解:

package oop.demo15_annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.ElementType.LOCAL_VARIABLE;

//自定义的注解
@MyAnnotation("自定义的注解")
@Target({TYPE,FIELD, METHOD,CONSTRUCTOR})//限制注解能注解的范围,比如TYPE,可以注解类,接口;CONSTRUCTOR可以注解构造器
@Retention(RetentionPolicy.SOURCE)//限制注解存在的生命周期,SOURCE(源代码中存在)、CLASS(字节码中存在)、RUNTIME(运行时也存在)
public @interface MyAnnotation {
    String value() default "Hello";//后面跟个default "Hello",意思就是没写String value(),他就默认用Hello

}

上面测试类AnnotationTest输出:

在这里插入图片描述


JUnit单元测试

单元测试大纲

Junit单元测试的使用:

1.需要导入的jar包:
Junit-4.12.jar
hamcrest-core-1.3.jar

2.导入步骤:
见笔记图片步骤


3.创建单元测试类,进行测试
见代码

4.(重点关注)要想能正确的编写单元测试方法,需要满足:
1. 所在的类必须是public的,非抽象的,包含唯一的无参构造器。
2. @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。


5.默认情况下,单元测试方法中使用Scanner失效。如何解决?
最上面找到Help——点击Edit Custom VM Options...
——在-javaagent:C:jetbrains-agent.jar下面加这一句-Deditable.java.test.console=true
然后重启idea就可以输入了。

6.以后写代码会经常写单元测试方法,大家可以将单元测试方法设置为一个模板
怎么设置模板:
File——Settings...(设置)——Editor——Live Templates——点右面的“ + ”——Template Group...(先自己定义个组)
——CustomDefine(用户自定义),OK——在建的组里面再点“ + ”——Live Template——在Abbreviation(希望通过什么可以调出来)中写test
——Description(说明)中写自动生成单元测试方法
——Template text:(模板长什么样子)中写
@Test
public void test$var1$(){   //var变亮
    $var2$
}
最后在下面Define,我们希望在java相关的逻辑中使用,选中Java,OK
  • 测试分类

黑盒测试:不需要写代码,给输入值,看程序是否能够输出期望的值。

白盒测试:需要写代码的。关注程序具体的执行流程。

在这里插入图片描述

在这里插入图片描述

  • JUnit单元测试介绍

JUnit是由Erich Gamma和Kent Beck编写的一个测试框架(regression testing framework),供java开发人员编写单元测试之用。

JUnit测试是程序猿测试,即所谓白盒测试,因为程序员知道被测试时的软件如何(HOW),完成功能和完成什么样(What)的功能。

要使用JUnit,必须在项目的编译路径中引入JUnit的库,即相关的.class文件组成的.jar包。jar就是一个压缩包,压缩包都是开发好的第三方(Oracle公司第一方,我们自己第二方,其他都是第三方)工具类,都是以.class文件形式存在的。
本地包(我也是网上搜索包名下载的)
在这里插入图片描述

  • 引入本地JUnit.jar

(1)在这里插入图片描述

(2)在这里插入图片描述

(3)在这里插入图片描述

(4)在这里插入图片描述

(5)在这里插入图片描述

(6)检查一下Modules——Dependencies下的包是不是Compile。
在这里插入图片描述

(7)查看

在这里插入图片描述

注: 其他模块底下没有导入用到的jar包,怎么能调用且使用@Test单元测试

新建模块

这个模块用来学习单元测试@test不在这个模块底下,怎么添加用起来
1.让导入的jar包让这个模块用起来就能用@Test单元测试
- File——Project Structure...——Modules——选中junit_test——Dependencies——点击右边“ + ”,Library...
- 选中JUnit-libs包-Add selected——把右边Test改成Compile——Apply——Ok

2.在有网的情况下:
- 点到报红@Test那一行,Alt+Enter
- 点击Add "JUnit4'to classpath,然后OK,他就开始有网下载了
package junit_test;

import org.junit.Test;

public class JUnitOutTest {

    @Test
    public void test(){
        System.out.println("Hello");
    }
}

编写和运行@Test单元测试方法

JUnit4版本,要求@Test标记的方法必须满足如下要求:

  1. 所在的类必须是public的,非抽象的,包含唯一的无参构造器。
  2. @Test标记的方法本身必须是public,非抽象的,非静态的,void无返回值,()无参数的。
package oop.demo15_annotation.juint;

import org.junit.Test;

import java.util.Scanner;

public class JunitTest {    //单元测试类
    public static void main(String[] args) {
        JunitTest test = new JunitTest();
        System.out.println(test.number);
        test.method();
    }

    int number = 10;

    //无参构造器
//    public JunitTest() {    //单元测试类只能有一个构造器且是无参构造器,默认就有无参构造,干脆单元测试类直接不写构造器
//    }

    @Test
    public void test1(){    //单元测试方法
        System.out.println("Hello");//Hello
    }

    //可以列很多个单元测试方法
    @Test   //这里只运行这一个模块底下的,不像main方法,如果运行,连上面的,下面的都会运行,或者要把其他的注释了,导入这个包用"@test"单元测试就行了
    public void test2(){
        System.out.println("hello2");//hello2
        System.out.println(number);//10

        method();//输出method()...

        int num = showInfo("China");//China
        System.out.println(num);//1
    }

    public void method(){
        System.out.println("method()...");
    }

    //上面单元测试方法底下调用
    public int showInfo(String info){
        System.out.println(info);
        return 1;
    }

    //默认情况下,单元测试方法中使用Scanner失效,不能输入,解决办法看单元测试大纲
    @Test
    public void test3(){
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入一个数值:");
        int num = scanner.nextInt();
        System.out.println(num);
    }

    //模板里面添加了自动生成单元测试方法,测试一下(怎么添加模板看大纲)
    @Test
    public void test4(){
        System.out.println("Hello");
    }

    @Test
    public void test5(){
        System.out.println("hello,冰默");
    }

}

添加模板:

怎么设置模板:
File——Settings…(设置)——Editor——Live Templates——点右面的“ + ”——Template Group…(先自己定义个组)
——CustomDefine(用户自定义),OK——在建的组里面再点“ + ”——Live Template

——在Abbreviation(希望通过什么可以调出来)中写test
——Description(说明)中写自动生成单元测试方法
——Template text:(模板长什么样子)中写
@Test
public void test v a r 1 var1 var1(){ //var变亮
v a r 2 var2 var2
}
最后在下面Define,我们希望在java相关的逻辑中使用,选中Java,OK

在这里插入图片描述

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。