导语:
一、Junit单元测试
1.Junit测试概述
2.Junit使用步骤
3.Junit_@Before&@After
二、反射
1.反射概述
2.反射获取字节码Class对象的三种方式
3.Class对象功能概述
4.Class对象功能_获取Field
5.Class对象功能_获取Constructor
6.Class对象功能_获取Method
7.反射案例
三、注解
1.注解概念
2.JDK内置注解
3.自定义注解_格式&本质
4.自定义注解_属性定义
5.自定义注解_元注解
6.解析注解
7.注解案例_简单的测试框架
结语:
导语:
这篇文档详细介绍了Java编程中Junit测试、反射原理和注解应用的核心知识点,旨在帮助初学者掌握Java基础,也可作为进阶学习的参考资料。
一、Junit单元测试
1.Junit测试概述
-
黑盒测试:无需编写代码,只需给输入值,检查输出是否符合预期。
-
白盒测试:需要编写代码,关注程序的具体执行流程。
案例代码:
展示了如何使用JUnit进行黑盒测试和白盒测试:
public class Calculator {public int add(int a, int b) {return a + b;}public int subtract(int a, int b) {return a - b;}
}
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;public class CalculatorTest {private Calculator calculator;@Beforepublic void setUp() {calculator = new Calculator();}// 黑盒测试@Testpublic void testAdd() {int result = calculator.add(1, 2);assertEquals(3, result);}// 白盒测试@Testpublic void testSubtract() {int result = calculator.subtract(5, 3);assertEquals(2, result);}
}
2.Junit使用步骤
-
定义测试类(以Test结尾)
-
定义测试方法(以test开头)
-
给测试方法添加@Test注解
-
导入Junit依赖
案例代码:
import org.junit.Assert;
import org.junit.Test;public class CalculatorTest {@Testpublic void testAdd() {Calculator c = new Calculator();int result = c.add(1, 2);Assert.assertEquals(3, result);}@Testpublic void testSubtract() {Calculator c = new Calculator();int result = c.subtract(5, 3);Assert.assertEquals(2, result);}
}
<dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope>
</dependency>
3.Junit_@Before&@After
-
@Before:初始化方法,在测试方法执行前自动执行
-
@After:释放资源方法,在测试方法执行后自动执行
代码案例:
import org.junit.After;
import org.junit.Before;
import org.junit.Test;public class CalculatorTest {private Calculator calculator;@Beforepublic void setUp() {// 初始化操作calculator = new Calculator();System.out.println("setUp...");}@Afterpublic void tearDown() {// 释放资源calculator = null;System.out.println("tearDown...");}@Testpublic void testAdd() {int result = calculator.add(1, 2);Assert.assertEquals(3, result);}@Testpublic void testSubtract() {int result = calculator.subtract(5, 3);Assert.assertEquals(2, result);}
}
二、反射
1.反射概述
-
将类的各个组成部分封装为其他对象
-
好处:在运行时操作对象,提高程序扩展性
代码案例:
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;public class ReflectionExample {public static void main(String[] args) {try {// 获取类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public字段Field[] fields = personClass.getFields();for (Field field : fields) {System.out.println("Public field: " + field);}// 获取所有public方法Method[] methods = personClass.getMethods();for (Method method : methods) {System.out.println("Public method: " + method);}// 获取所有public构造器Constructor<?>[] constructors = personClass.getConstructors();for (Constructor<?> constructor : constructors) {System.out.println("Public constructor: " + constructor);}} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
2.反射获取字节码Class对象的三种方式
-
Class.forName()
-
类名.class
-
对象.getClass()
代码案例:
public class ReflectionExample {public static void main(String[] args) {// 方式1:使用Class.forName()try {Class<?> personClass1 = Class.forName("Person");System.out.println(personClass1);} catch (ClassNotFoundException e) {e.printStackTrace();}// 方式2:使用类名.classClass<?> personClass2 = Person.class;System.out.println(personClass2);// 方式3:使用对象.getClass()Person person = new Person();Class<?> personClass3 = person.getClass();System.out.println(personClass3);}
}
3.Class对象功能概述
-
获取成员变量
-
获取构造方法
-
获取成员方法
-
获取全类名
案例代码:
public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有成员变量Field[] fields = personClass.getDeclaredFields();for (Field field : fields) {System.out.println("Field: " + field);}// 获取所有构造方法Constructor<?>[] constructors = personClass.getDeclaredConstructors();for (Constructor<?> constructor : constructors) {System.out.println("Constructor: " + constructor);}// 获取所有成员方法Method[] methods = personClass.getDeclaredMethods();for (Method method : methods) {System.out.println("Method: " + method);}// 获取全类名String className = personClass.getName();System.out.println("Full class name: " + className);} catch (ClassNotFoundException e) {e.printStackTrace();}}
}
4.Class对象功能_获取Field
-
Field[] getFields()
-
Field getField(String name)
-
Field[] getDeclaredFields()
-
Field getDeclaredField(String name)
案例代码:
public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public字段Field[] publicFields = personClass.getFields();for (Field field : publicFields) {System.out.println("Public Field: " + field);}// 获取指定名称的public字段Field publicField = personClass.getField("name");System.out.println("Specific Public Field: " + publicField);// 获取所有字段(包括private)Field[] allFields = personClass.getDeclaredFields();for (Field field : allFields) {System.out.println("Field: " + field);}// 获取指定名称的字段(包括private)Field privateField = personClass.getDeclaredField("age");System.out.println("Specific Field: " + privateField);} catch (ClassNotFoundException | NoSuchFieldException e) {e.printStackTrace();}}
}
5.Class对象功能_获取Constructor
-
Constructor[] getConstructors()
-
Constructor getConstructor(参数类型…)
-
Constructor getDeclaredConstructor(参数类型…)
-
Constructor[] getDeclaredConstructors()
案例代码:
public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public构造器Constructor<?>[] publicConstructors = personClass.getConstructors();for (Constructor<?> constructor : publicConstructors) {System.out.println("Public Constructor: " + constructor);}// 获取指定参数的public构造器Constructor<?> publicConstructor = personClass.getConstructor(String.class);System.out.println("Specific Public Constructor: " + publicConstructor);// 获取所有构造器(包括private)Constructor<?>[] allConstructors = personClass.getDeclaredConstructors();for (Constructor<?> constructor : allConstructors) {System.out.println("Constructor: " + constructor);}// 获取指定参数的构造器(包括private)Constructor<?> privateConstructor = personClass.getDeclaredConstructor(String.class, int.class);System.out.println("Specific Constructor: " + privateConstructor);} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();}}
}
6.Class对象功能_获取Method
-
Method[] getMethods()
-
Method getMethod(String name, 参数类型…)
-
Method[] getDeclaredMethods()
-
Method getDeclaredMethod(String name, 参数类型…)
案例代码:
public class ReflectionExample {public static void main(String[] args) {try {// 获取Person类的Class对象Class<?> personClass = Class.forName("Person");// 获取所有public方法Method[] publicMethods = personClass.getMethods();for (Method method : publicMethods) {System.out.println("Public Method: " + method);}// 获取指定名称和参数的public方法Method publicMethod = personClass.getMethod("setName", String.class);System.out.println("Specific Public Method: " + publicMethod);// 获取所有方法(包括private)Method[] allMethods = personClass.getDeclaredMethods();for (Method method : allMethods) {System.out.println("Method: " + method);}// 获取指定名称和参数的方法(包括private)Method privateMethod = personClass.getDeclaredMethod("showAge");System.out.println("Specific Method: " + privateMethod);} catch (ClassNotFoundException | NoSuchMethodException e) {e.printStackTrace();}}
}
7.反射案例
-
从配置文件读取类名和方法名
-
使用反射加载类、创建对象、执行方法
案例代码:
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;public class ReflectionExample {public static void main(String[] args) {try {// 加载配置文件Properties properties = new Properties();InputStream inputStream = ReflectionExample.class.getClassLoader().getResourceAsStream("config.properties");properties.load(inputStream);// 读取配置文件中的类名和方法名String className = properties.getProperty("class.name");String methodName = properties.getProperty("method.name");// 使用反射加载类Class<?> classObj = Class.forName(className);// 使用反射创建对象Object obj = classObj.newInstance();// 使用反射执行方法Method method = classObj.getMethod(methodName);method.invoke(obj);} catch (ClassNotFoundException e) {e.printStackTrace();} catch (NoSuchMethodException e) {e.printStackTrace();} catch (InstantiationException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}
三、注解
1.注解概念
-
说明程序,给计算机看的
-
分类:文档、代码分析、编译检查
案例代码
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 文档注解
@Deprecated
public class AnnotationExample {// 编译检查注解@Overridepublic String toString() {return "This is a overridden toString method";}// 代码分析注解@SuppressWarnings("unchecked")public void analyzeCode() {// 这里会有类型转换的警告Object obj = new Object();String str = (String) obj;}// 自定义注解@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {String value() default "";}@MyAnnotation("Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}
2.JDK内置注解
-
@Override
-
@Deprecated
-
@SuppressWarnings
案例代码:
public class AnnotationExample {// 使用@Override注解标记重写父类方法@Overridepublic String toString() {return "This is a overridden toString method";}// 使用@Deprecated注解标记已过时的方法@Deprecatedpublic void oldMethod() {System.out.println("This is an old method");}// 使用@SuppressWarnings注解压制编译器警告@SuppressWarnings("unchecked")public void analyzeCode() {// 这里会有类型转换的警告Object obj = new Object();String str = (String) obj;}
}
3.自定义注解_格式&本质
-
本质是接口,默认继承Annotation接口
案例代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 注解的作用目标
@Retention(RetentionPolicy.RUNTIME) // 注解的保留策略
public @interface MyAnnotation {// 定义一个value属性String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并指定value属性值@MyAnnotation(value = "Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}
4.自定义注解_属性定义
-
返回值类型:基本数据类型、String、枚举、注解、数组
-
属性赋值
案例代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 注解的作用目标
@Retention(RetentionPolicy.RUNTIME) // 注解的保留策略
public @interface MyAnnotation {// 定义一个String类型的value属性,并指定默认值为"Hello"String value() default "Hello";// 定义一个int类型的age属性int age();// 定义一个枚举类型的gender属性Gender gender();// 定义一个注解类型的anno属性MyAnnotation2 anno();// 定义一个String数组类型的tags属性String[] tags();
}// 定义一个枚举类型
enum Gender {MALE, FEMALE
}// 定义一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation2 {String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并为所有属性赋值@MyAnnotation(value = "World", age = 30, gender = Gender.MALE, anno = @MyAnnotation2("anno2"), tags = {"tag1", "tag2"})public void annotatedMethod() {System.out.println("Annotated method");}
}
5.自定义注解_元注解
-
@Target
-
@Retention
-
@Documented
-
@Inherited
案例代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD) // 指定该注解只能用于方法
@Retention(RetentionPolicy.RUNTIME) // 指定注解保留到运行时
@Documented // 指定该注解会被包含在javadoc中
@Inherited // 指定该注解可以被继承
public @interface MyAnnotation {// 定义一个String类型的value属性,并指定默认值为"Hello"String value() default "Hello";
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解@MyAnnotation("World")public void annotatedMethod() {System.out.println("Annotated method");}
}// 继承了父类的注解
public class ChildClass extends AnnotationExample {// 子类会继承父类的@MyAnnotation注解@Overridepublic void annotatedMethod() {System.out.println("Child class");}
}
6.解析注解
-
获取注解定义位置的对象
-
获取指定的注解
-
调用注解方法获取属性值
案例代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;// 定义一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {// 定义一个String类型的value属性String value();
}// 使用自定义注解
public class AnnotationExample {// 在方法上使用自定义注解,并指定value属性值@MyAnnotation(value = "Hello")public void annotatedMethod() {System.out.println("Annotated method");}
}// 解析注解
public class AnnotationParser {public static void main(String[] args) throws Exception {// 获取方法对象Method method = AnnotationExample.class.getMethod("annotatedMethod");// 获取方法上的MyAnnotation注解MyAnnotation myAnnotation = method.getAnnotation(MyAnnotation.class);// 调用注解方法获取value属性值String value = myAnnotation.value();// 输出value属性值System.out.println("Value: " + value);}
}
7.注解案例_简单的测试框架
-
自定义注解
-
定义测试类
-
执行测试
案例代码:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;// 定义一个自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {// 定义一个String类型的value属性String value();
}// 定义一个测试类
public class TestClass {// 定义一个测试方法,并使用自定义的Test注解@Test(value = "测试 add 方法")public void testAdd() {int result = 1 + 2;assertEquals(3, result);}@Test(value = "测试 subtract 方法")public void testSubtract() {int result = 5 - 3;assertEquals(2, result);}// 定义一个断言方法public static void assertEquals(int expected, int actual) {if (expected != actual) {throw new RuntimeException("测试失败:期望值=" + expected + " 实际值=" + actual);}}
}// 执行测试
public class TestRunner {public static void main(String[] args) {Class<?> testClass = TestClass.class;try {// 获取测试类对象Object testInstance = testClass.newInstance();// 遍历测试类中的所有方法for (Method method : testClass.getMethods()) {// 检查方法是否使用了Test注解if (method.isAnnotationPresent(Test.class)) {try {// 执行测试方法method.invoke(testInstance);System.out.println("测试成功:" + method.getAnnotation(Test.class).value());} catch (Exception e) {System.out.println("测试失败:" + method.getAnnotation(Test.class).value());}}}} catch (Exception e) {e.printStackTrace();}}
}
结语:
以上内容涵盖了JUnit单元测试、反射机制、注解的概念及自定义,以及如何解析注解并应用在简单的测试框架案例中。这些知识点对于Java后端开发中的框架设计、代码规范以及测试都非常重要。通过这些知识点的学习,可以加深对Java高级特性的理解,并为后续框架学习和项目开发打下基础。
#JavaWeb
欢迎大家交流,金三银四求职季期间关注公众号送面试宝典。