目录
1.Junit单元测试
1.概念:
针对最小的功能(方法),完成单独测试,测试该方法正确性
2.怎么做:
1.导入jar包依赖
2.在测试类中 设计测试方法(格式)
1.无参
2.无返回值
3.公共的
4.@Test:注解:让程序知道这里是做测试的方法。
3.测试
前面会有 绿色箭头 点击即可 或者右键 run运行
如果是ok 绿色 否则 红色
3.断言机制:
断言:即预测divide的值 应该等于预期的2.如果不符合预期,这个方法会抛出异常,单元测试不通过 Assert.assertEquals(预测结果, 实际结果);
4.测试注解:
package com.itheima.day14.teacher.demo01_junit;
//案例一:
import org.junit.*;
/**
* 单元测试的注解:
* 1. @Test:加在实例方法(非静态方法)上,idea会给方法提供运行按钮,可以直接运行这个方法
* 2. @Before:加在实例方法上。方法会在 每次运行@Test方法之前,先执行一次
* 3. @After:加在实例方法上。方法会在 每次运行@Test方法之后,再执行一次
* 4. @BeforeClass:加在静态方法上。方法会在整个类里所有@Test之前执行,只执行一次
* 5. @AfterClass:加在静态方法上。方法会在整个类里所有@Test之后执行,只执行一次
* 使用场景:
* 所有的前置的注解@Before、@BeforeClass,通常用于初始化一些资源
* 所有的后置的注解@After、@AfterClass,用于用于最终的资源释放
*/
public class Demo02Test {
@Test
public void test1(){
System.out.println("test1");
}
@Test
public void test2(){
System.out.println("test2");
}
@Before
public void before(){
System.out.println("--before--");
}
@After
public void after(){
System.out.println("--after--");
}
@BeforeClass
public static void beforeAll(){
System.out.println("==beforeClass==");
}
@AfterClass
public static void afterAll(){
System.out.println("==afterClass==");
}
}
----------------------
//案例二:
package com.itheima.day14.teacher.demo01_junit;
public class MathUtil {
/**
* 判断一个数字是否偶数。这个方法是正确的
*/
public static boolean isEven(int n){
return n % 2 == 0;
}
/**
* 两数相除。a 除以 b。 这个方法是有问题的
*/
public static int divide(int a, int b){
return b / a;
}
}
---
package com.itheima.day14.teacher.demo01_junit;
import org.junit.Assert;
import org.junit.Test;
public class Demo01MathUtilTest {
@Test
public void testIsEven(){
boolean even = MathUtil.isEven(10);
//断言:即预测even的值是true。如果值不符合预期,这个方法会抛出异常,单元测试不通过
Assert.assertTrue(even);
}
@Test
public void testDivide(){
int divide = MathUtil.divide(6, 3);
//断言:即预测divide的值 应该等于预期的2.如果不符合预期,这个方法会抛出异常,单元测试不通过
Assert.assertEquals(2, divide);
}
@Test
public void test1(){
//方法不抛异常,所以测试结果是 测试通过
System.out.println("xxxxx");
}
@Test
public void test2(){
//方法会抛异常,所以测试结果是 测试不通过
int i = 1/0;
}
}
2.反射
1.概念:
就是加载类字节码文件到内存,以编程方式 解剖类中各个成分(构造器,成员属性,成员方法) 。
就是将类中各个成分封装成了对应对象的过程。
2.需要掌握的API
1.获取字节码对象三种方式+Class类型
Class.forName(包名+类名) jvm去加载该包下的类到内存。
类名.class 类文件到内存
对象.getClass() 类优先于对象到内存,且对象是基于类产生。
String.class int.class Integer.class等等
package com.itheima.day14.teacher.demo02_reflect;
import org.junit.Test;
/**
*/
public class Demo01Class {
/**
* 获取类的Class:
*/
@Test
public void testClass() throws ClassNotFoundException {
//类名.class
Class<Student> clazz = Student.class;
System.out.println("clazz = " + clazz);
//对象.getClass()
Student stu = new Student();
Class<? extends Student> clazz2 = stu.getClass();
System.out.println("clazz2 = " + clazz2);
//Class.forName("全限定类名")
Class<?> clazz3 = Class.forName("demo02_reflect.Demo01Class");
System.out.println("clazz3 = " + clazz3);
}
/**
* 从Class对象里获取类的信息
*/
@Test
public void testClass2(){
Class<Student> clazz = Student.class;
//获取完整类名:demo02_reflect.Student
System.out.println(clazz.getName());
//获取简单类名:Student
System.out.println(clazz.getSimpleName());
}
}
--------------------------
package com.itheima.day14.teacher.demo02_reflect;
import org.junit.Test;
public class Demo01Class {
/**
* 获取类的Class:
*/
@Test
public void testClass() throws ClassNotFoundException {
//类名.class
Class<Student> clazz = Student.class;
System.out.println("clazz = " + clazz);
//对象.getClass()
Student stu = new Student();
Class<? extends Student> clazz2 = stu.getClass();
System.out.println("clazz2 = " + clazz2);
//Class.forName("全限定类名")
Class<?> clazz3 = Class.forName("demo02_reflect.Demo01Class");
System.out.println("clazz3 = " + clazz3);
}
/**
* 从Class对象里获取类的信息
*/
@Test
public void testClass2(){
Class<Student> clazz = Student.class;
//获取完整类名:demo02_reflect.Student
System.out.println(clazz.getName());
//获取简单类名:Student
System.out.println(clazz.getSimpleName());
}
}
2.获取构造器 Constructor
package com.itheima.day14.teacher.demo02_reflect;
public class Student {
public String name;
private Integer age;
public Student() {
}
private Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public void eat(String food){
System.out.println("吃" + food);
}
private String sleep(int time){
System.out.println("睡" + time + "小时");
return "睡不醒";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
----------------
package com.itheima.day14.teacher.demo02_reflect;
import org.junit.Test;
import java.lang.reflect.Constructor;
/**
* 构造方法:用于创建类的实例对象的
* 调用构造方法的方式有两种:
* 普通方式:new 构造方法名(实参列表)
* 反射方式:
* 1. 先获取类的Class
* 2. 从Class里获取构造方法对应的Constructor
* clazz.getConstructors():得到Constructor[],获取类里所有的public构造方法
* clazz.getDeclaredConstructors():得到Constructor[],获取类里所有的构造方法
* clazz.getConstructor(Class... parameterTypes):根据形参类型,找到对应的public构造方法
* clazz.getDeclaredConstructor(Class... parameterTypes):根据形参类型,找到对应的构造方法
* 3. 调用Constructor的方法,就会生成类的实例对象
* constructor.newInstance(Object... args):调用构造方法并传入构造参数,得到生成的实例对象
* constructor.setAccessible(boolean flag):设置一下,是否允许暴力反射调用
*/
public class Demo02Constructor {
/**
* 获取一批构造方法
*/
@Test
public void testGetConstructors(){
//1. 先获取类的Class
Class<Student> clazz = Student.class;
//2. 获取所有public构造方法
// Constructor<?>[] constructors = clazz.getConstructors();
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
for (Constructor<?> constructor : constructors) {
System.out.println("constructor = " + constructor);
}
}
/**
* 获取某一个构造方法
*/
@Test
public void testGetConstructor() throws NoSuchMethodException {
//1. 先获取类的Class
Class<Student> clazz = Student.class;
//2. 获取无参的构造方法
Constructor<Student> constructor = clazz.getConstructor();
System.out.println("constructor = " + constructor);
//3. 获取全参构造方法:
// 是private的,所以要使用getDeclaredConstructor方法
// 如果要获取有参的构造方法,需要getDeclaredConstructor传入 构造方法的形参类型列表
// 要查找第一个形参是String类型的,第二个形参是Integer类型的 构造方法
Constructor<Student> constructor1 = clazz.getDeclaredConstructor(String.class, Integer.class);
System.out.println("constructor1 = " + constructor1);
}
/**
* 反射调用无参构造方法 创建实例对象
*/
@Test
public void testNewInstance1() throws Exception {
//1. 获取类的Class
Class<Student> clazz = Student.class;
//2. 获取无参构造方法
Constructor<Student> constructor = clazz.getConstructor();
//3. 调用无参构造,得到实例对象
Student student = constructor.newInstance();
System.out.println("student = " + student);
Student student1 = new Student();
System.out.println("student1 = " + student1);
}
/**
* 反射调用有参构造,创建实例对象
*/
@Test
public void testNewInstance2() throws Exception {
//1. 获取类的Class
Class<Student> clazz = Student.class;
//2. 获取无参构造方法
Constructor<Student> constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
//3. 因为是private的,所以需要暴力反射
constructor.setAccessible(true);
//4. 调用无参构造,得到实例对象
Student student = constructor.newInstance("郭宇", 18);
System.out.println("student = " + student);
}
}
3. 获取成员方法Method
package com.itheima.day14.teacher.demo02_reflect;
/**
*/
public class Student {
public String name;
private Integer age;
public Student() {
}
private Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public void eat(String food){
System.out.println("吃" + food);
}
private String sleep(int time){
System.out.println("睡" + time + "小时");
return "睡不醒";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
------------------------
package com.itheima.day14.teacher.demo02_reflect;
import org.junit.Test;
import java.lang.reflect.Method;
/**
* 调用一个对象的方法,有两种方式,最终效果相同:
* 普通方式:Object res = 对象.方法名(实参列表);
* 反射方式:
* 1. 先获取类的Class
* 2. 从Class里获取普通方法对应的Method
* clazz.getMethods():获取所有public方法
* clazz.getDeclaredMethod():获取所有方法
* clazz.getMethod(String name, Class... parameterTypes):获取指定public方法
* clazz.getDeclaredMethod(String name, Class... parameterTypes)
* 3. 反射调用Method,传入方法的实参,得到方法的返回值
* Object res = method.invoke(对象, 实参列表)
*/
public class Demo03Method {
/**
* 反射调用public方法:Student的eat方法
*/
@Test
public void test1() throws Exception {
Student student = new Student();
student.eat("爆肚面");
System.out.println("----------------");
//1. 获取Class
Class<? extends Student> clazz = student.getClass();
//2. 获取Method:获取名称为eat,第一个形参是String的方法
Method eatMethod = clazz.getMethod("eat", String.class);
//3. 调用Method:method.invoke(对象, 实参列表)
Object res = eatMethod.invoke(student, "鸡");
System.out.println("res = " + res);
}
/**
* 反射调用private方法:sleep
*/
@Test
public void test2() throws Exception {
Student s = new Student();
//1. 获取Class
Class<? extends Student> clazz = s.getClass();
//2. 获取Method
Method sleepMethod = clazz.getDeclaredMethod("sleep", int.class);
//3. 设置允许暴力反射
sleepMethod.setAccessible(true);
//4. 反射调用Method
Object res = sleepMethod.invoke(s, 8);
System.out.println("res = " + res);
}
}
4.获取成员属性Field
package com.itheima.day14.teacher.demo02_reflect;
public class Student {
public String name;
private Integer age;
public Student() {
}
private Student(String name, Integer age) {
this.name = name;
this.age = age;
}
public void eat(String food){
System.out.println("吃" + food);
}
private String sleep(int time){
System.out.println("睡" + time + "小时");
return "睡不醒";
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
---------------------
package com.itheima.day14.teacher.demo02_reflect;
import org.junit.Test;
import java.lang.reflect.Field;
/**
* 反射操作成员变量,两种方式,最终效果相同:
* 普通方式:
* 对象.成员变量名 = 值
* Object value = 对象.成员变量名
* 反射方式:
* 1. 获取类的Class
* 2. 从Class里获取成员变量对应的Field
* clazz.getFields():获取所有public的成员变量
* clazz.getDeclaredFields():获取所有成员变量
* clazz.getField(String fieldName):获取一个public的成员变量
* clazz.getDeclaredField(String fieldName):获取一个成员变量
* 3. 反射操作Field,赋值或取值
* field.set(对象, 值):给成员变量赋值
* Object value = field.get(对象):取成员变量的值
*/
public class Demo04Field {
/**
* 操作public的field
*/
@Test
public void test1() throws NoSuchFieldException, IllegalAccessException {
Student s = new Student();
//1. 获取Class
Class<? extends Student> clazz = s.getClass();
//2. 获取Field
Field nameField = clazz.getField("name");
//3. 操作Field
// 给成员变量赋值
nameField.set(s, "小明");
System.out.println(s);
// 反射取成员变量值
Object value = nameField.get(s);
System.out.println("value = " + value);
}
/**
* 反射操作age成员变量
*/
@Test
public void test2() throws Exception {
Student s = new Student();
//1. 获取Class
Class<? extends Student> clazz = s.getClass();
//2. 获取Field
Field ageField = clazz.getDeclaredField("age");
//3. 反射操作Field
ageField.setAccessible(true);
ageField.set(s, 18);
System.out.println("s = " + s);
Object value = ageField.get(s);
System.out.println("value = " + value);
}
}
注意:绕过权限检查 setAccessable(true)
3.注解
1.注解:就是用于在代码标识,被程序解析
编译检查 @Override
让程序指定特定操作,@Test
2.注解的定义
public @Interface 注解名{}
属性 属性类型 属性名() default 默认值;
value注解可以省略,其他属性不用赋值情况下。
3.元注解:修饰注解的注解
常见的两种:
4.通过反射机制解析 注解 注解一种对象 Annotation对象
package com.itheima.day14.teacher.demo03_anno;
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.TYPE, ElementType.METHOD})
public @interface MyAnno {
int age() default 18;
boolean status() default false;
String value();
}
--------------------
package com.itheima.day14.teacher.demo03_anno;
import java.util.Date;
/**
*/
@SuppressWarnings(value = {"unused"})
public class Demo01 {
/**
* 如果方法上加了@Override:这个注解本身没有任何功能
* 作用是:给idea看的。
* 当idea发现某个方法上有这个注解,idea就会帮我们检查 这个方法是否符合重写的语法要求
* 如果不符合,idea会报错
*/
@Override
public String toString() {
return "Demo01{}";
}
public static void main(String[] args) {
Demo01 demo01 = new Demo01();
System.out.println(demo01);
Date date = new Date(2024, 3, 21);
System.out.println("date = " + date);
String abc = "abc";
}
}
-------------------
package com.itheima.day14.teacher.demo03_anno;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
*/
@SuppressWarnings("all")
@MyAnno(status = false, value = "abc")
public class Demo02MyAnno {
@MyAnno(age = 28, status = true, value = "ac")
public void show(){
System.out.println("show");
}
/**
* 1.自定义一个注解MyAnno;其中包含一些属性
* 2.定义一个类,类里show方法上加MyAnno注解,并给属性赋值
* 3.在类里写一个main方法, 判断show方法上有没有MyAnno注解;如果有,就获取配置的注解对象,并取参数值打印出来
*/
@MyAnno("xxx")
public static void main(String[] args) throws NoSuchMethodException {
//要求:判断一下show方法上有没有MyAnno注解;如果有的话,就获取注解配置的属性参数值
// 获取类的Class
Class<Demo02MyAnno> clazz = Demo02MyAnno.class;
// 从类的Class获取show方法的Method
Method showMethod = clazz.getMethod("show");
// 再调用Method对象的isAnnotationPresent方法,判断有没有MyAnno注解
boolean b = showMethod.isAnnotationPresent(MyAnno.class);
System.out.println("Demo02MyAnno类里的show方法上是否有@MyAnno注解:" + b);
//就获取注解配置的属性参数值
MyAnno myAnno = showMethod.getAnnotation(MyAnno.class);
System.out.println(myAnno.age());
System.out.println(myAnno.status());
System.out.println(myAnno.value());
System.out.println("------------------------");
//@SuppressWarnings这个注解的功能,idea是怎么实现的?
// 判断类上有没有@Suppresswarnings注解,如果有的话获取value值。根据value值不同,压制不同的警告
// 这里得到结果是false,注解不存在。
// 原因是:@SuppressWarnings的RetentionPolicy是SOURCE,只保留到源码阶段;而这里通过反射判断有没有注解,反射是在运行时阶段的
boolean suppressWarnings = clazz.isAnnotationPresent(SuppressWarnings.class);
System.out.println(suppressWarnings);
if (suppressWarnings) {
SuppressWarnings annotation = clazz.getAnnotation(SuppressWarnings.class);
String[] value = annotation.value();
System.out.println("要压制的警告有:" + Arrays.toString(value));
}
}
}