[winter vacation 2020] Day1 Java advanced

Keywords: Java calculator Junit Attribute

What java needs to learn today is:

1. Junit unit test

2. reflection

3. notes

Junit unit test:

  • Test classification:
  1. Black box test: no need to write code, give input value, see whether the program can output the expected value.
  2. White box test: need to write code. Pay attention to the specific execution process of the procedure.
  • How we used to test classes:
package cn.itcast.junit;

/**
 * Calculator class
 */
public class Calculator {


    /**
     * addition
     * @param a
     * @param b
     * @return
     */
    public int add (int a , int b){
        //int i = 3/0;

        return a - b;
    }

    /**
     * subtraction
     * @param a
     * @param b
     * @return
     */
    public int sub (int a , int b){
        return a - b;
    }

}
package cn.itcast.junit;

public class CalculatorTest {

    public static void main(String[] args) {

        //create object
        Calculator c = new Calculator();
        //call
       /* int result = c.add(1, 2);
        System.out.println(result);*/

        int result = c.sub(1, 1);
        System.out.println(result);

        String str = "abc";
    }
}

This is the general test method that we usually teach in school. First, define a test class, and then assign a value to see the difference between the test result and the expected result.

Let's learn a new test method

  • Junit use: white box test

  • Steps:

  1. Define a test class (test case)
  2. Define test method: can run independently
  • Recommendation:
    • Method name: the method name of the test testAdd()
    • Return value: void
    • Parameter list: empty parameter
  1. Add @ Test to the method
  2. Import junit dependent environment
  • Judgment result:
    • Red: failed
    • Green: success
    • In general, we use assertion operations to process results
    • Assert. Assertequals (expected result, result of operation);

* supplement:

  • @Before:
  • The decorated method is automatically executed before the method is tested
  • @After:
  • The decorated method is automatically executed after the test method is executed
package cn.itcast.junit;

/**
 * Calculator class
 */
public class Calculator {


    /**
     * addition
     * @param a
     * @param b
     * @return
     */
    public int add (int a , int b){
        //int i = 3/0;

        return a - b;
    }

    /**
     * subtraction
     * @param a
     * @param b
     * @return
     */
    public int sub (int a , int b){
        return a - b;
    }

}
package cn.itcast.test;

import cn.itcast.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest {
    /**
     * Initialization method:
     *  For resource request, all test methods will execute the method before execution
     */
    @Before
    public void init(){
        System.out.println("init...");
    }

    /**
     * Release resources by:
     *  After all test methods are executed, the method is executed automatically
     */
    @After
    public void close(){
        System.out.println("close...");
    }


    /**
     * Test add method
     */
    @Test
    public void testAdd(){
       // System.out.println("I was executed");
        //1. Create calculator object
        System.out.println("testAdd...");
        Calculator c  = new Calculator();
        //2. Call add method
        int result = c.add(1, 2);
        //System.out.println(result);

        //3. Assert that I assert that the result is 3
        Assert.assertEquals(3,result);

    }

    @Test
    public void testSub(){
        //1. Create calculator object
        Calculator c  = new Calculator();
        int result = c.sub(1, 2);
        System.out.println("testSub....");
        Assert.assertEquals(-1,result);
    }
}

Result:

Because there is a logic error of addition in the computer class, the result of the test class will be shown in red. If I change the addition back to normal, the result is as follows:

Green if right

Reflection: the soul of frame design

  • Framework: semi-finished software. Software development can be carried out on the basis of framework to simplify coding
  • Reflection: encapsulates the components of a class as other objects, which is the reflection mechanism
  • Benefits:
    ==1. These objects can be operated during program running. = =
    ==2. It can decouple and improve the scalability of the program. = =
  • How to get the Class object:
  1. Class.forname: load the bytecode file into memory and return the class object
  • Most of them are used for configuration files, and the class name is defined in the configuration file. Read file, load class
  1. Class name. Class: obtained by the attribute class of class name
  • Mostly used for parameter passing
  1. Object. getClass(): the getClass() method is defined in the object class.
  • How to get bytecode for objects
package cn.itcast.reflect;

import cn.itcast.domain.Person;
import cn.itcast.domain.Student;

public class ReflectDemo1 {


    /**
        How to get the Class object:
            1. Class.forName("Full Class name "): load the bytecode file into memory and return the Class object
            2. Class name. Class: obtained by the attribute class of class name
            3. Object. getClass(): the getClass() method is defined in the object class.

     */
    public static void main(String[] args) throws Exception {

        //1.Class.forName("full class name")
        Class cls1 = Class.forName("cn.itcast.domain.Person");
        System.out.println(cls1);
        //2. class name
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3. Object. getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);

        //==Compare three objects
        System.out.println(cls1 == cls2);//true
        System.out.println(cls1 == cls3);//true


        Class c = Student.class;
        System.out.println(c == cls1);


    }
}

  • Conclusion:
    The same bytecode file (*. class) will only be loaded once during a program run, and the class object obtained in any way is the same.

  • Class object function:

  • Get function:

  1. Get member variables
  • Field[] getFields(): get all public decorated member variables
  • Field getField(String name) gets the public decorated member variable of the specified name
  • Field[] getDeclaredFields() gets all member variables, regardless of modifiers
  • Field getDeclaredField(String name)
  1. Get constructors
  • Constructor<?>[] getConstructors()
  • Constructor getconstructor (class <? > parameterTypes)
  • Constructor getdeclaredconstructor (class <? > parameterTypes)
  • Constructor<?>[] getDeclaredConstructors()
  1. Get member methods:
  • Method[] getMethods()
  • Method getMethod(String name, class <? > parameterTypes)
  • Method[] getDeclaredMethods()
  • Method getDeclaredMethod(String name, class <? > parameterTypes)
  1. Get full class name
    String getName()

Field: member variable

  • Operation:
  1. Set value
  • void set(Object obj, Object value)
  1. Get value
  • get(Object obj)
  1. Ignore security check for access modifier
  • setAccessible(true): violent reflection

Constructor: construction method

  • Create object:
  • T newInstance(Object... initargs)
  • If an object is created with a null parameter construction method, the operation can be simplified: newInstance method of Class object

==Method: Method Object==

  • Execution method:
  • Object invoke(Object obj, Object... args)
  • Get method name:
  • String getName: get method name

Take the member variable as an example:

package cn.itcast.reflect;

import cn.itcast.domain.Person;

import java.lang.reflect.Field;

public class ReflectDemo2 {


    /**
     Class Object function:
         * Get function:
         1. Get member variables
             * Field[] getFields()
             * Field getField(String name)

             * Field[] getDeclaredFields()
             * Field getDeclaredField(String name)
         2. Get constructors
             * Constructor<?>[] getConstructors()
             * Constructor<T> getConstructor(Class <? >... Parametertypes)

             * Constructor<T> getDeclaredConstructor(Class <? >... Parametertypes)
             * Constructor<?>[] getDeclaredConstructors()
         3. Get member methods:
             * Method[] getMethods()
             * Method getMethod(String name, Class <? >... Parametertypes)

             * Method[] getDeclaredMethods()
             * Method getDeclaredMethod(String name, Class <? >... Parametertypes)

         4. Get class name
             * String getName()



     */

    public static void main(String[] args) throws Exception {

        //0. Get the Class object of Person
        Class personClass = Person.class;
        /*
             1. Get member variables
                 * Field[] getFields()
                 * Field getField(String name)

                 * Field[] getDeclaredFields()
                 * Field getDeclaredField(String name)

         */
        //1.Field[] getFields() gets all public decorated member variables
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        System.out.println("------------");
        //2.Field getField(String name)
        Field a = personClass.getField("a");
        //Get the value of member variable a
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);
        //Set the value of a
        a.set(p,"Zhang San");
        System.out.println(p);

        System.out.println("===================");

        //Field[] getDeclaredFields(): get all member variables without considering modifiers
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
        //Field getDeclaredField(String name)
        Field d = personClass.getDeclaredField("d");
        //Ignore security check for access modifier
        d.setAccessible(true);//Violent reflection
        Object value2 = d.get(p);
        System.out.println(value2);
    }
}

Here, in order to facilitate everyone to understand the concept of reflection, I made a small case.

  • Case study:
  • Requirement: write a "framework" that can help us create objects of any class and execute any methods of any class without changing any code of the class
  • Realization:
  1. configuration file
  2. reflex
  • Steps:
  1. Define the full class name of the object to be created and the method to be executed in the configuration file
  2. Load read profile in program
  3. Using reflection technology to load class files into memory
  4. create object
  5. Execution method
package cn.itcast.reflect;

import cn.itcast.domain.Person;
import cn.itcast.domain.Student;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * Frame class
 */
public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //You can create objects of any class and execute any method

        /*
            Premise: no code of this class can be changed. You can create objects of any class and execute any method
         */
      /*  Person p = new Person();
        p.eat();*/
/*
        Student stu = new Student();
        stu.sleep();*/

        //1. Load configuration file
        //1.1 create Properties object
        Properties pro = new Properties();
        //1.2 loading configuration files, converting to a collection
        //1.2.1 get the configuration file under the class directory
        ClassLoader classLoader = ReflectTest.class.getClassLoader();
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2. Get the data defined in the configuration file
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");


        //3. Load this class into memory
        Class cls = Class.forName(className);
        //4. Create object
        Object obj = cls.newInstance();
        //5. Get method object
        Method method = cls.getMethod(methodName);
        //6. Implementation method
        method.invoke(obj);


    }
}

Profile:

className=cn.itcast.domain.Student
methodName=sleep

Notes:

  • Concept: describing the procedure. For the computer

  • Note: describes the program in text. For programmers

  • Definition: Annotation, also known as metadata. A code level description. It is a feature introduced by JDK 1.5 and later. It is at the same level as class, interface and enumeration. It can be declared in front of package, class, field, method, local variable, method parameter, etc. to explain and comment these elements.

  • Concept description:

    • New features after JDK 1.5
    • Describing the procedure
    • Use annotation: @ annotation name
  • Action classification:
    ① Document preparation: generate document (generate document doc document) through the annotation identified in the code
    ② Code analysis: analyze the code through the annotation identified in the code [use reflection]
    ③ Compile check: the compiler can realize basic compile check [Override] through the annotation identified in the code

Note editing document presentation:

package cn.itcast.annotation;

/**
 * Annotate javadoc demo
 *
 * @author itcat
 * @version 1.0
 * @since 1.5
 */


public class AnnoDemo1 {

    /**
     * Calculate the sum of two numbers
     * @param a integer
     * @param b integer
     * @return Sum of two numbers
     */




       /**** 
       * @Description: add 
       *   * @param a
        * @param b 
       * @return: int 
       * @Author: Mr.Cao
       * @Date: 2018/6/18 
       */ 
    public int add(int a, int b ){
        return a + b;
    }
    /**
    * @Description: summ
    * @Param: [a, b]
    * @return: int
    * @Author: Mr.Cao
    * @Date: 2018/6/18    tab+a+/
    */




    public  int summ(int a,int b){
        return a+b;
    }
}

Compiling documents with javadoc

Some files are generated:

Open index.html

  • Some predefined annotations in JDK
  • @Override: check whether the method annotated by the annotation inherits from the parent class (Interface)
  • @Deprecated: the content of the annotation, indicating that it is obsolete
  • @SuppressWarnings: suppress warnings
  • General pass parameter all @ suppresswarnings ("all")
package cn.itcast.annotation;

import java.util.Date;

/**
 * JDK Some annotations predefined in
 *        * @Override    : Check whether the method marked by the annotation inherits from the parent class (Interface)
 *        * @Deprecated: The annotation indicates that it is out of date
 *        * @SuppressWarnings: Suppression warning
 *
 *
 */

@SuppressWarnings("all")
public class AnnoDemo2 {

    @Override
    public String toString() {
        return super.toString();
    }

    @Deprecated//Overdue annotations
    public void show1(){
        //Defective
    }


    public void show2(){
        //Replace show1 method
    }


    public void demo(){
        show1();
        Date date = new Date();
    }
}
  • Custom annotation
  • Format:
    Meta annotation
    public @interface annotation name{
    Attribute list;
    }
  • Essence: Annotation is essentially an interface, which inherits Annotation interface by default
    • public interface MyAnno extends java.lang.annotation.Annotation {}
  • Properties: abstract methods in interfaces
    • Requirement:
    1. The return value type of the property has the following values
    • Basic data type
    • String
    • enumeration
    • annotation
    • Array of the above types
package cn.itcast.annotation;

import com.sun.corba.se.spi.orbutil.threadpool.Work;

public @interface MyAnno {

     int value();
    Person per();
    MyAnno2 anno2();
    String[] strs();
     /*String name() default "Zhang San;*/
     /*String show2();

     Person per();
     MyAnno2 anno2();

     String[] strs();*/


}
  1. The property is defined and needs to be assigned a value when it is used
    1. If the default keyword is used to initialize the default value of a property when defining a property, the annotation can be used without assigning a value to the property.
    2. If only one attribute needs to be assigned, and the name of the attribute is value, then value can be omitted and the value can be defined directly.
    3. When the array is assigned, the value is wrapped with {}. If there is only one value in the array, {} can be omitted
  • Meta annotation: annotation used to describe annotation
    • @Target: describes where annotations can work
      • ElementType value:
        • TYPE: can act on a class
        • METHOD: can act on the METHOD
        • FIELD: can act on member variables
    • @Retention: describes the stage in which the annotation is retained
      • @Retention(RetentionPolicy.RUNTIME): the currently described annotation will be kept in the class bytecode file and read by the JVM
    • @Documented: describes whether annotations are extracted into api documents
    • @Inherited: describes whether the annotation is inherited by a subclass
package cn.itcast.annotation;

import java.lang.annotation.*;

@Target(value = {ElementType.TYPE,ElementType.FIELD,ElementType.METHOD})//Describe where annotations are used
@Retention(RetentionPolicy.RUNTIME)//Describe when annotations are used
@Documented
@Inherited
public @interface MyAnno4 {
}

Continue with the above case, and we will use the annotation method to do it again:

package cn.itcast.annotation;

import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * Frame class
 */


@Pro(className = "cn.itcast.annotation.Demo1",methodName = "show")
public class ReflectTest {
    public static void main(String[] args) throws Exception {

        /*
            Premise: no code of this class can be changed. You can create objects of any class and execute any method
         */


        //1. Explanatory notes
        //1.1 get the bytecode file object of this class
        Class<ReflectTest> reflectTestClass = ReflectTest.class;
        //2. Get the annotation object above
        //In fact, a subclass implementation object of the annotation interface is generated in memory
        /*

            public class ProImpl implements Pro{
                public String className(){
                    return "cn.itcast.annotation.Demo1";
                }
                public String methodName(){
                    return "show";
                }

            }
 */

        Pro an = reflectTestClass.getAnnotation(Pro.class);
        //3. Call the abstract method defined in the annotation object to get the return value
        String className = an.className();
        String methodName = an.methodName();
        System.out.println(className);
        System.out.println(methodName);
        //3. Load this class into memory
        Class cls = Class.forName(className);
        //4. Create object
        Object obj = cls.newInstance();
        //5. Get method object
        Method method = cls.getMethod(methodName);
        //6. Implementation method
        method.invoke(obj);
    }
}

We just need to change the contents of @ pro to realize the above functions
  • Using (parsing) annotations in a program: getting attribute values defined in annotations
  1. Object (Class, Method,Field) to get the location of annotation definition
  2. Get the specified annotation
  • getAnnotation(Class)
//In fact, a subclass implementation object of the annotation interface is generated in memory
  public class ProImpl implements Pro{
               public String className(){
                   return "cn.itcast.annotation.Demo1";
               }
               public String methodName(){
                   return "show";
               }
           }

Case: simple test framework

package cn.itcast.annotation.demo;


/**
 * Calculator class defined by Xiao Ming
 */
public class Calculator {

    //addition
    @Check
    public void add(){
        String str = null;
        str.toString();
        System.out.println("1 + 0 =" + (1 + 0));
    }
    //subtraction
    @Check
    public void sub(){
        System.out.println("1 - 0 =" + (1 - 0));
    }
    //multiplication
    @Check
    public void mul(){
        System.out.println("1 * 0 =" + (1 * 0));
    }
    //division
    @Check
    public void div(){
        System.out.println("1 / 0 =" + (1 / 0));
    }


    public void show(){
        System.out.println("Never bug...");
    }

}

check annotation

package cn.itcast.annotation.demo;


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

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

Test class:

package cn.itcast.annotation.demo;


import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Simple test framework
 *
 * When the main method is executed, it will automatically detect all the methods (with Check annotation) by itself, judge whether there is any exception in the method, and record it in the file
 */
public class TestCheck {


    public static void main(String[] args) throws IOException {
        //1. Create calculator object
        Calculator c = new Calculator();
        //2. get bytecode file object
        Class cls = c.getClass();
        //3. Get all methods
        Method[] methods = cls.getMethods();

        int number = 0;//Number of exceptions
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));


        for (Method method : methods) {
            //4. Judge whether there is a Check comment on the method
            if(method.isAnnotationPresent(Check.class)){
                //5. Yes, implementation
                try {
                    method.invoke(c);
                } catch (Exception e) {
                    //6. Catch exception

                    //Record to file
                    number ++;

                    bw.write(method.getName()+ " There's something wrong with the method");
                    bw.newLine();
                    bw.write("Name of exception:" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("Cause of abnormality:"+e.getCause().getMessage());
                    bw.newLine();
                    bw.write("--------------------------");
                    bw.newLine();

                }
            }
        }

        bw.write("This test appears in total "+number+" Secondary anomaly");

        bw.flush();
        bw.close();



    }

}

From this result, it can be seen that only two operations are tested successfully, and the other two tests are unsuccessful. At this time, a bug.txt file will be generated in the project file:

Summary:

  1. Most of the time, we will use annotations instead of custom annotations
  2. For whom?
    1. Compiler
    2. For parser
  3. Annotation is not a part of the program. It can be understood that annotation is a label
Published 16 original articles, won praise 3, visited 348
Private letter follow

Posted by curtis_b on Sun, 12 Jan 2020 19:38:07 -0800