Java advanced—Junit unit testing, reflection, annotations

**

1. Junit unit testing

**

Test category:

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

When we encounter such a problem: we can only test one method at a time, because only one main method can be written in a class. If we want to test multiple methods, and each method is independent of each other, we can use Junit to solve it.

Junit usage steps:

1.定义一个测试类
	编写格式建议:
		测试类名:被测试的类名Test,例如CalTest
		包名:xxx.xxx.test,最终放在test包中
2.定义测试方法:可以独立运行
	编写格式建议:
		方法名:test测试的方法名,例如testAdd()
		返回值:void,因为独立运行,不需要返回给调用处
		参数列表:空参,因为独立运行,不需要返回给调用处
3.给方法加上@Test注解,加上以后,就可以独立运行了
4.导入Junit依赖环境,否则加上@Test之后会报错

judgement result:

1.运行后显示红色:失败
2.运行后显示绿色:成功
一般会使用断言操作来处理结果:
	Assert.assertEquals(期望的结果,程序运行的结果);

annotation:

1.@Before:修饰的方法会在测试方法之前被自动执行
	初始化方法:用于资源申请,所有测试方法在执行之前都会执行该方法。我们可以在一个方法前面加上注解@Before,使其成为一个初始化方法。
2.@After:修饰的方法会在测试方法之后自动被执行
	释放资源的方法:在所有测试方法执行完后,都会自动执行该方法。我们可以在一个方法前面加上注解@After,使其成为一个释放资源的方法

Note:
In unit testing, output is generally not written, because looking at the output cannot determine whether the program is correct. The presence of output can only indicate that the code syntax is correct, but the logic may be incorrect.
Therefore, we generally use assertion operations to determine whether there is a problem with the code. We will compare the assertion result with the true result. If the assertion is successful, it will be displayed in green after running; if the assertion fails, it will be displayed in red after running.

**

2. Reflection: the soul of frame design

**
2.1 Framework

Frameworks are half-finished software. Software development can be carried out on the basis of the framework and coding can be simplified.
Writing a framework requires reflection, and parts outside the framework do not require reflection technology. So reflection is the internal implementation principle of the framework.

2.2 Reflection

Encapsulating various components of a class into other objects is the reflection mechanism.

For example, the Class object will

成员变量封装成了Field[] fileds对象
构造方法封装成了Constructor[] constructors对象
成员方法封装成了Method[] methods对象

Benefits of reflection:

1.可以在程序运行过程中,操作这些对象。
	例如String str = "abc";
	str.写完(.)之后,会将字符串对象str所具有的的方法都提示出来,因为将所有的方法都封装到了Method[]数组中,这就是用到了反射技术,IDEA打开期间都可以提示,这就是程序运行时
2.可以解耦,即降低程序的耦合性,提高程序的可扩展性

2.3 There are three ways to obtain Class objects, corresponding to the three stages of Java code:

1.Source源代码阶段:Class.forName("全类名")
	将字节码文件加载进内存,返回Class对象
	全类名即包名+类名
	因为传递的是字符串,所以多用于配置文件,将类名定义在配置文件中,读取文件,加载类
2.Class对象阶段:类名.Class
	通过类名的属性class获取
	多用于参数的传递
3.Runtime运行时阶段:对象.getClass()
	getClass方法是封装在Object类中的方法,所以所有对象都可以调用该方法
	多用于对象的获取字节码的方式
4.结论(重要!!!)
	同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方式获取的Class对象都是同一个

2.4 Functions of Class objects—getting functions:

1.获取成员变量们
    Field[] getFields():获取所有public修饰的成员变量
    Field[] getField(String name):获取指定名称的public修饰的成员变量

    Field[] getDeclaredFields():获取所有的成员变量,不考虑修饰符
    Field[] getDeclaredField(String name):获取指定名称的成员变量,需忽略访问权限修饰符的安全检查
2.获取构造方法们
    Constructor[] getConstructors()
    Constructor[] getConstructor(类<?>... parameterTypes)

    Constructor[] getDeclaredConstructors()
    Constructor[] getDeclaredConstructor(类<?>... parameterTypes)
3.获取成员方法们
    Method[] getMethods()
    Method[] getMethod(String name, 类<?>... parameterTypes)

    Method[] getDeclaredMethods()
    Method[] getDeclaredMethod(String name, 类<?>... parameterTypes)
4.获取类名
    String getName()

注意:带Declared的方法都需要忽略访问权限修饰符的安全检查
    setAccessible(true)

Filed (member variable):

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

Constructor:

创建对象:
    T newInstance(Object... initargs)
如果使用空参数构造方法创建对象,可以简化操作:使用Class对象的newInstance方法

Method (member method):

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

2.5 The three stages that Java code goes through in the computer

1) Source source code stage (.java --> .class)

After the .java file is compiled by javac, a .class bytecode file is generated. The main contents contained in the .class file are: member variables, construction methods, and member methods.

2) Class object stage

Xxx.class (bytecode file) can be loaded into memory through the class loader (ClassLoader).
In the memory, there will be an object to describe the bytecode. There is a class in Java called the Class class. This object is the Class class object. The Class class is used to describe some common behaviors and attributes of the bytecode file.

The main parts of the Class object:

成员变量:封装为了Field[] fields对象
构造方法:封装为了Constructor[] constructors对象
成员方法:封装为了Method[] methods对象

3) Runtime stage

We can create real objects through some behaviors of the Class object: new Person();

2.6 Write a “framework”

need:

不能改变该类的任何代码,可以创建任意类的对象,可以执行任意方法

technology:

配置文件、反射

accomplish:

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

Code:

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //可以创建任意类的对象,可以执行任意方法

        /*
            前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
         */

        //下述方法,在创建不同对象,执行其方法的时候,需要修改代码
//        Person p = new Person();
//        p.eat();

//        Student stu = new Student();
//        stu.sleep();

        //1.加载配置文件
        //1.1 创建Properties对象
        Properties prop = new Properties();
        //1.2 加载配置文件,转换为一个集合
        //1.2.1 获取文件的路径,即获取class目录下的配置文件:使用【类加载器】,后续可以将字节码文件加载进内存
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        prop.load(is);

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

        //3.加载该类进内存
        Class cls = Class.forName(className);

        //4.创建对象
        Object obj = cls.newInstance();
        //5.获取方法对象
        Method method = cls.getMethod(methodName);
        //6.执行方法
        method.invoke(obj);
    }
}

**

3. Notes

**

3.1 Concept

Annotation is also Annotation. Starting from JDK5, Java adds support for metadata, which is annotation.
There is a certain difference between annotations and annotations. Annotations can be understood as special marks in the code. These marks can be read during compilation, class loading, and runtime, and corresponding processing can be performed. Comments describe the program in words and are for programmers to see.
Through annotations, developers can embed supplementary information in the source code without changing the original code and logic.

3.2 Function classification

1) Write documentation: Generate documents through the metadata (annotations) identified in the code [Generate document doc document]

2) Code analysis: Analyze the code through the metadata (annotations) identified in the code [using reflection]

3) Compilation check: The compiler can implement basic compilation check [override] through the metadata (annotations) identified in the code. If it is rewritten correctly, the compilation will pass.

3.3 How to use annotations

@annotation name

3.4 Java provides 5 basic annotations:

1.@Override: Check whether the method marked by this annotation is inherited from the parent class (interface)

2.@Deprecated: The content marked by this annotation indicates that it is outdated.

3.@SuppressWarnings: Suppress warnings. Generally, the parameter all is passed to suppress all warnings: @SuppressWarnings("all")

4.@SafeVarargs: Heap pollution warning

5.@FunctionalInterface: Functional interface

3.5 Custom annotations

1) Format

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

2) Essence

Annotation is essentially an interface, which inherits the Annotation interface by default.

3) Properties

Attributes: member methods that can be defined in the interface; that is, abstract methods are attributes of annotations

There are following requirements for attributes:

1.属性的返回值类型有如下选择:

    基本数据类型
    String(字符串)
    枚举
    注解
    以上类型的数组

2.定义了属性,在使用时,需要给属性赋值

    1.如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不进行属性的赋值

    2.如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可。

    3.数组赋值时,值使用{}包裹:
        大括号中有多个值:例如@MyAnno(strs = {"abc", "def"})
        大括号中只有一个值,则大括号{}可以省略,例如@MyAnno(strs =  "abc")

3.6 Meta-annotations

Meta-annotations are annotations used to describe annotations

1) @Target: Describes where the annotation can act (on the class or method)

ElementType取值:

     TYPE:可以作用于类上,@Target(value = ElementType.TYPE)
     METHOD:可以作用于方法上,@Target(value = ElementType.METHOD)
     FIELD:可以作用于成员变量上,@Target(value = ElementType.FIELD)

     若想同时作用于多个位置,可以用大括号{}:@Target(value = {ElementType.TYPE, ElementType.METHOD})
     因为只有一个属性需要赋值,且属性名为value,则可以省略:
         @Target(ElementType.TYPE, ElementType.METHOD)

2) @Target: Describes where the annotation can act (on the class or method)

RetentionPolicy value:

SOURCE:当前被描述的注解,【不会】保留到class字节码文件中,【不会】被JVM读取到

CLASS:当前被描述的注解,【会】保留到class字节码文件中,【不会】被JVM读取到

RUNTIME:当前被描述的注解,【会】保留到class字节码文件中,【并被】JVM读取到

Note: Generally, custom annotations are set to RUNTIME.

3) @Documented: Describes whether the annotation is extracted into the API document

@Documented //表示MyAnno3这个注解会被抽取到javadoc文档中
public @interface MyAnno3 {
}

4) @Inherited: Describes whether the annotation is inherited by subclasses

@Inherited  //表示子类自动继承该注解
public @interface MyAnno3 {
}

3.7 Summary of annotation usage

1. Most of the time in the future, we will use annotations instead of custom annotations.
2. Who are annotations for?
1. Used by the compiler
2. Used by the parsing program, such as TestCheck.java
3. The annotation is not part of the program, it can be understood that the annotation is a label

Guess you like

Origin blog.csdn.net/weixin_42214237/article/details/126294276