What java needs to learn today is:
1. Junit unit test
2. reflection
3. notes
Junit unit test:
- Test classification:
- Black box test: no need to write code, give input value, see whether the program can output the expected value.
- 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:
- Define a test class (test case)
- Define test method: can run independently
- Recommendation:
- Method name: the method name of the test testAdd()
- Return value: void
- Parameter list: empty parameter
- Add @ Test to the method
- 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:
- 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
- Class name. Class: obtained by the attribute class of class name
- Mostly used for parameter passing
- 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:
- 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)
- Get constructors
- Constructor<?>[] getConstructors()
- Constructor getconstructor (class <? > parameterTypes)
- Constructor getdeclaredconstructor (class <? > parameterTypes)
- Constructor<?>[] getDeclaredConstructors()
- Get member methods:
- Method[] getMethods()
- Method getMethod(String name, class <? > parameterTypes)
- Method[] getDeclaredMethods()
- Method getDeclaredMethod(String name, class <? > parameterTypes)
- Get full class name
String getName()
Field: member variable
- Operation:
- Set value
- void set(Object obj, Object value)
- Get value
- get(Object obj)
- 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:
- configuration file
- reflex
- Steps:
- Define the full class name of the object to be created and the method to be executed in the configuration file
- Load read profile in program
- Using reflection technology to load class files into memory
- create object
- 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:
- 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();*/ }
- The property is defined and needs to be assigned a value when it is used
- 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.
- 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.
- 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
- ElementType value:
- @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
- @Target: describes where annotations can work
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
- Object (Class, Method,Field) to get the location of annotation definition
- 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:
- Most of the time, we will use annotations instead of custom annotations
- For whom?
- Compiler
- For parser
- Annotation is not a part of the program. It can be understood that annotation is a label