十五、泛型(完结)
十五、泛型
15.1 泛型的引入
15.1.1 集合添加指定类型元素问题
需求:请编写程序,在 ArrayList
中,添加3个 Dog
对象,Dog
对象含有 name
和 age
,并输出 name
和 age
(要求使用getXxx()
)
15.1.2 使用传统方法解决
package com.hspedu.generic;
import java.util.ArrayList;
/**
* @author Carl Zhang
* @description
* @date 2021/12/12 13:17
*/
public class Generic {
public static void main(String[] args) {
//需求 请编写程序,在ArrayList中,添加3个Dog对象
//Dog对象含有name和age,并输出name和age(要求使用getXxx())
//传统方法:
ArrayList arrayList = new ArrayList();
arrayList.add(new Dog("二狗", 2));
arrayList.add(new Dog("小白", 1));
arrayList.add(new Dog("老黑", 5));
arrayList.add("赵四"); //
for (Object o : arrayList) {
Dog o1 = (Dog) o; //遍历到赵四的时候,抛异常 ClassCastException
System.out.println("name = " + o1.getName() + ", age = "
+ o1.getAge());
}
//问题:1. 无法对集合里传入的元素类型做限制
// 2. 每次使用都要进行类型转换,数据量大的时候影响效率
}
}
class Dog {
private String name;
private int age;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
15.1.2 传统方法的弊端
- 无法对集合里传入的元素类型做限制
- 每次使用都要进行类型转换,数据量大的时候影响效率
15.1.3 使用泛型解决
package com.hspedu.generic;
import java.util.ArrayList;
/**
* @author Carl Zhang
* @description
* @date 2021/12/12 20:39
*/
public class Generic02 {
public static void main(String[] args) {
//用泛型解决问题
ArrayList<Dog> dogs = new ArrayList<>();
dogs.add(new Dog("二狗", 2));
dogs.add(new Dog("小白", 1));
dogs.add(new Dog("老黑", 5));
//dogs.add("赵四"); //添加别的类型编译报错
for (Dog dog :dogs) { //可以直接获取Dog 类型元素
System.out.println("name = " + dog.getName() + ", age = "
+ dog.getAge());
}
//好处:
//1. 可以在编译时对集合里的元素类型进行限制
//2. 使用时不用每次都向下转型,可以直接获取对应类型元素,效率提高
}
}
15.2 泛型的理解与好处
15.2.1 泛型的好处
- 编译时可以对添加的元素类型进行检查,提高安全性,防止
ClassCastException
异常 - 使用时不用每次都向下转型,可以直接获取对应类型元素,效率提高
15.2.2 泛型的介绍
- 泛型又称参数化类型,是
Jdk5.0
出现的新特性,解决数据类型的安全性问题 - 在类声明或实例化时只要指定好需要的具体的类型即可。
Java
泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException
异常。同时,代码更加简洁健壮- 泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型。
package com.hspedu.generic;
/**
* @author Carl Zhang
* @description
* @date 2021/12/12 20:59
*/
public class Generic03 {
public static void main(String[] args) {
//解读:
//1. class Person<E> 中 E 表示泛型标识,可以接收任意类型,E也可以用其他字母表示
//2. new Person<String>(); 表示将String类型传递给E , 指定E的类型为String
//3. E 的具体类型在创建对象的时候就指定,即在编译阶段就会确定 E 的类型
Person<String> person = new Person<String>();
person.name = "赵四";
//person.name = 33; //传入不同的类型,编译报错
person.show();
}
}
//泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,
// 或者是某个方法的返回值的类型,或者是参数类型
class Person<E> { //在类声明时通过标识符 E 表示类中对应变量的类型
E name; //属性name的类型是 E,E的具体类型在实例化Person对象的时候指定
public void p(E e) { //参数e 的类型是E
System.out.println(e);
}
public E p2() { //返回值的类型是E
return name;
}
public void show() {
System.out.println(name.getClass()); //通过getClass() 查看name的具体类型
}
}
15.3 泛型的语法
15.3.1 泛型的语法
- 声明语法:
interface 接口<T> {}
、class 类<K,V> {}
T
、K
、V
不代表具体值,只表示类型- 任意字母、任意数量。常用
T
,Type
缩写
- 实例化语法:在类名后面指定类型参数的值
- 例:
HashSet<Student> students = new HashSet<Student>();
- 例:
15.3.2 案例
需求:
- 创建3个学生对象
- 放入到
HashSet
中学生对象,使用 - 放入到
HashMap
中,要求Key
是String name
,Value
就是学生对象 - 使用两种方式遍历
package com.hspedu.generic;
import javafx.scene.chart.ValueAxis;
import java.util.*;
/**
* @author: Carl Zhang
* @create: 2021-12-13 09:23
*/
public class GenericExercise01 {
public static void main(String[] args) {
//1.创建3个学生对象
Student stu1 = new Student("赵四", 25);
Student stu2 = new Student("马大帅", 23);
Student stu3 = new Student("德彪", 26);
//2.放入到HashSet中学生对象,使用.
HashSet<Student> students = new HashSet<Student>();
students.add(stu1);
students.add(stu2);
students.add(stu3);
//forEach遍历
System.out.println("forEach遍历");
for (Student stu : students) {
System.out.println(stu);
}
System.out.println();
//Iterator 遍历
System.out.println("Iterator 遍历");
Iterator<Student> iterator = students.iterator();
while (iterator.hasNext()) {
Student next = iterator.next();
System.out.println(next);
}
System.out.println();
//3.放入到HashMap中,要求Key 是String name,Value就是学生对象
HashMap<String, Student> studentHashMap = new HashMap<String, Student>();
studentHashMap.put(stu1.getName(), stu1);
studentHashMap.put(stu2.getName(), stu2);
studentHashMap.put(stu3.getName(), stu3);
//4.使用两种方式遍历
//通过entrySet遍历
System.out.println("通过entrySet遍历");
Set<Map.Entry<String, Student>> stuEntries = studentHashMap.entrySet();
/*
//new 对象的时候指定了K、V的类型,所以Set<Map.Entry<String, Student>>编译会通过,通过.var会自动填充
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
final class EntrySet extends AbstractSet<Map.Entry<K,V>> {.....} AbstractSet 实现了 Set接口
*/
System.out.println("stuEntries.getClass() = " + stuEntries.getClass()); //HashMap$EntrySet
for (Map.Entry stuEntry : stuEntries) {
System.out.println(stuEntry.getValue());
}
System.out.println();
//通过values遍历
System.out.println("通过values遍历");
Collection<Student> values = studentHashMap.values();
/*
public Collection<V> values() {
Collection<V> vs = values;
if (vs == null) {
vs = new Values();
values = vs;
}
return vs;
}
*/
Iterator<Student> iterator1 = values.iterator();
/*
//debug查看源码:最终返回的是一个HashMap$ValueIterator类型的iterator,V = Student
public final Iterator<V> iterator() { return new ValueIterator(); }
final class ValueIterator extends HashIterator
implements Iterator<V> {
public final V next() { return nextNode().value; }
}
* */
System.out.println("iterator1.getClass() = " + iterator1.getClass()); //HashMap$ValueIterator
while (iterator1.hasNext()) {
Student next = iterator1.next();
System.out.println(next);
}
System.out.println();
//查看运行类型
System.out.println("stuEntries.getClass() = " + stuEntries.getClass()); //HashMap$EntrySet
}
}
15.3.3 泛型使用细节
- 泛型标识符只能接收引用类型
- 在给泛型指定具体类型后,可以传入该类型或者其子类类型
- 泛型的使用形式
HashMap<String, Student> studentHashMap = new HashMap<String, Student>();
Map<String, Student> studentHashMap = new HashMap<String, Student>();
HashMap<String, Student> studentHashMap = new HashMap<>();
推荐
- 不指定类型,默认类型是
Object
ArrayList arrayList = new ArrayList();
等同于ArrayList<Object> objects = new ArrayList<>();
- 注意:泛型只在编译时期限定数据的类型 , 在运行时期会被擦除。后面学习反射的时候,可以实现在代码运行的过程中添加其他类型的数据到集合 见 20.7.4
15.4 泛型使用案例
package com.hspedu.generic;
import java.util.ArrayList;
import java.util.Comparator;
/**
* @author: Carl Zhang
* @create: 2021-12-13 10:57
*/
public class GenericExercise02 {
public static void main(String[] args) {
//5.1 new Employee(name, sal, birthday)*3 将元素添加到集合 new ArrayList<Employee>
//5.2 arrayList.sort(new Comparator<Employee>(){
// public int compare(Employee emp1, Employee emp2) {
// //声明变量保存排序结果
// int res = -1;
// //调用String的compareTo()方法
// if ((res = emp1.getName().compareTo(emp2.getName())) != 0)
// return res
// //比较生日日期 --> 实现Comparable接口,重写compareTo方法
// //比较规则:按照年月日顺序比较,返回年月日的差值
// return emp1.getBirthday().compareTo(emp2.getBirthday())
// }
// })
ArrayList<Employee> employees = new ArrayList<>();
employees.add(new Employee("赵四", 20000, new MyDate("1999", "01", "01")));
employees.add(new Employee("本山", 10000, new MyDate("1999", "01", "01")));
employees.add(new Employee("刘能", 20000, new MyDate("1999", "01", "01")));
employees.add(new Employee("赵四", 80000, new MyDate("1998", "01", "01")));
employees.add(new Employee("刘能", 30000, new MyDate("1999", "02", "01")));
employees.sort(new Comparator<Employee>() {
@Override
public int compare(Employee emp1, Employee emp2) {
//声明变量保存排序结果
int res = -1;
//调用String的compareTo()方法比较name
//res = emp1.getName().compareTo(emp2.getName());
if ((res = emp1.getName().compareTo(emp2.getName())) != 0)
return res; //name不同就返回name的比较结果
//比较生日日期 --> 实现Comparable接口,重写compareTo方法
//比较规则:按照年月日顺序比较,返回年月日的差值
//封装后,将来可维护性和复用性,就大大增强
return emp1.getBirthday().compareTo(emp2.getBirthday());
}
});
for (Employee o :employees) {
System.out.println(o);
}
}
}
package com.hspedu.generic;
import java.util.Objects;
/**
* @author: Carl Zhang
* @create: 2021-12-13 11:04
*/
public class MyDate implements Comparable<MyDate> {
//MyDate类 ,year,month,day属性 继承LocalDate类
//重写MyDate类的hashCode() ,equals()
private String year;
private String month;
private String day;
public MyDate(String year, String month, String day) {
this.year = year;
this.month = month;
this.day = day;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MyDate)) return false;
MyDate myDate = (MyDate) o;
return Objects.equals(year, myDate.year) &&
Objects.equals(month, myDate.month) &&
Objects.equals(day, myDate.day);
}
@Override
public int hashCode() {
return Objects.hash(year, month, day);
}
@Override
public String toString() {
return
"year:" + year + '\'' +
", month:'" + month + '\'' +
", day:'" + day + '\'' +
'}';
}
//比较生日日期 --> 实现Comparable接口,重写compareTo方法
//比较规则:按照年月日顺序比较,返回年月日的差值
@Override
public int compareTo(MyDate o) {
int res = -1;
int year1 = Integer.parseInt(year);
int year2 = Integer.parseInt(o.year);
//如果年不同,就return year 1 - year2
if ((res = year1 - year2) != 0)
return res;
//比较月
int month1 = Integer.parseInt(month);
int month2 = Integer.parseInt(o.month);
if ((res = month1 - month2) != 0)
return res;
//比较日
int day1 = Integer.parseInt(day);
int day2 = Integer.parseInt(o.day);
return day1 - day2;
}
}
public class Employee {...}
15.5 自定义泛型
15.5.1 自定义泛型类
语法:class Tiger<T, R, M> {}
要点:
Tiger
后面泛型,所以我们把Tiger
就称为自定义泛型类T
、R
、M
泛型的标识符,一般是单个大写字母- 泛型标识符可以有多个
- 普通成员可以使用泛型 (属性、方法)
- 泛型类型不能直接实例化
- 静态成员不能使用类的泛型(方法、属性)
- 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
- 如果在创建对象时,没有指定类型,默认为
Object
package com.hspedu.generic;
/**
* @author: Carl Zhang
* @create: 2021-12-13 13:28
*/
public class CustomGeneric {
public static void main(String[] args) {
Tiger<String, Integer, Double> tiger = new Tiger<>();
}
}
//1. Tiger 后面泛型,所以我们把 Tiger 就称为自定义泛型类
//2, T, R, M 泛型的标识符, 一般是单个大写字母
//3. 泛型标识符可以有多个.
class Tiger<T, R, M> {
String name;
//4. 普通成员可以使用泛型 (属性、方法)
T t;
public T m1(R r, M m) {
//5. 泛型类型不能直接实例化
// 数组:因为new对象的时候不知道具体类型,无法初始化对应空间
//T[] ts = new T[3]; //提示:类型参数'T'不能直接实例化
return t;
}
//6. 静态成员不能使用类的泛型(方法、属性)
// 因为静态成员是类相关的,如果静态成员使用了泛型,就无法初始化
//static T t2;
//public static void m2(T t, R r) { }
}
//7. 泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)
//8. 如果在创建对象时,没有指定类型,默认为Object
15.5.2 自定义泛型接口
语法:interface IA<T, R> {}
要点:
- 接口中,静态成员也不能使用泛型
- 泛型接口的类型, 在继承接口或者实现接口时确定
- 没有指定类型,默认为
Object
package com.hspedu.customgeneric;
/**
* @author: Carl Zhang
* @create: 2021-12-13 14:10
*/
public class CustomGenericInterface {
}
//1. 接口中,静态成员也不能使用泛型
interface IA<T, R> {
String D = "无名氏";
//T T1 = "test"; //接口的属性默认是public static final
void getT(T t); //接口中普通方法可以使用泛型
void getR(R r);
}
//2. 泛型接口的类型, 在继承接口或者实现接口时确定
class AA implements IA<String, Double> { //表示类AA实现接口IA时,指定了T是String类型,R是Double类型
@Override
public void getT(String s) {
System.out.println(s.getClass());
}
@Override
public void getR(Double d) {
System.out.println(d.getClass());
}
}
//3. 没有指定类型,默认为 Object
interface BB extends IA { //接口BB继承接口IA,没有指定T,R的类型,默认用Object
@Override
void getT(Object o);
@Override
void getR(Object o);
}
15.5.3 自定义泛型方法
语法:修饰符 <T, E> 返回值类型 方法名(参数列表) {}
要点:
- 泛型方法,可以定义在普通类中,也可以定义在泛型类中
- 当泛型方法被调用时传入参数,类型会确定
public void eat(T t, E e)
,修饰符后没有<T, E>
,eat
方法不是泛型方法,而是使用了泛型
package com.hspedu.customgeneric;
import com.hspedu.generic.Student;
/**
* @author: Carl Zhang
* @create: 2021-12-13 14:29
*/
public class CustomGenericMethod {
public static void main(String[] args) {
AAA aaa = new AAA();
//2.当泛型方法被调用时传入参数,类型会确定
aaa.methodA("赵四", 11); //t的类型class java.lang.String,
//e的类型class java.lang.Integer
String s = aaa.methodB("赵小四", 11);
System.out.println(s);
BBB<String, Double> bbb = new BBB<>();
bbb.eat("炒粉", 33d);
bbb.methodA("本山", 22); //q的类型class java.lang.String,
// w的类型class java.lang.Integer
String s1 = bbb.methodB("河粉", 2d);
System.out.println(s1);
}
}
//1.泛型方法,可以定义在普通类中,也可以定义在泛型类中
class AAA {
public <T, E> void methodA(T t, E e) { //定义在普通类的泛型方法
System.out.println("t的类型" + t.getClass() + ", e的类型" + e.getClass());
}
public <T, E> String methodB(T t, E e) { //定义在普通类的泛型方法
return "t的类型" + t.getClass() + ", e的类型" + e.getClass();
}
}
class BBB<T, E> {
public <Q, W> void methodA(Q q, W w) { //定义在泛型类的泛型方法
System.out.println("q的类型" + q.getClass() + ", w的类型" + w.getClass());
}
//可以使用自己声明的泛型,也可以使用类声明的泛型
public <Q, W> String methodB(T t, E e) { //定义在泛型类的泛型方法
return "t的类型" + t.getClass() + ", e的类型" + e.getClass();
}
//3.public void eat(Ee)0,修饰符后没有<T,R.>eat方法不是泛型方法,而是使用了泛型
public void eat(T t, E e) { //修饰符后没有<T, R> eat方法不是泛型方法,而是使用了泛型
System.out.println("t的类型" + t.getClass() + ", e的类型" + e.getClass());
}
}
15.6 泛型的继承和通配符
15.6.1 泛型的继承和通配符介绍
- 泛型没有继承性
<?>
表示任意类型都能接收<? extends A>
表示能接收A
类型及A
的子类类型,规定了泛型的上限<? super A>
表示能接收A
类型及A
的父类类型,规定了泛型的上限
15.6.2 案例
package com.hspedu.genericextend;
import java.util.ArrayList;
import java.util.List;
/**
* @author: Carl Zhang
* @create: 2021-12-13 15:08
*/
public class GenericExtend {
public static void main(String[] args) {
//1. 泛型没有继承性
//List<Object> strings = new ArrayList<String>(); //报错
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<AA> list3 = new ArrayList<>();
List<BB> list4 = new ArrayList<>();
List<CC> list5 = new ArrayList<>();
//能传入任意的泛型类型List
methodA(list1);
methodA(list2);
methodA(list3);
methodA(list4);
methodA(list5);
//methodB(list1); //报错 需要 List<? extends AA>, 提供了List<Object>
//表示集合的泛型类型为AA或继承了AA的类型
//methodB(list1); //报错,Object没继承AA
//methodB(list2); //报错,String没继承AA
methodB(list3);
methodB(list4);
methodB(list5);
//表示集合的泛型类型为BB或BB的父类,不限于直接父类
methodC(list1);
//methodC(list2); //报错,String 不是BB的父类或非直接父类
methodC(list3);
methodC(list4);
//methodC(list5); //报错,String 不是BB的父类或非直接父类
}
//2. <?> 表示任意类型都能接收
public static void methodA(List<?> list) { //List<?>表示任意类型都能接收
for (Object o : list) { // 通配符,取出时,就是 Object
System.out.println("o.getClass() = " + o.getClass());
}
}
//3. <? extends A>表示能接收 A 类型及 A 的子类类型,规定了泛型的上限
//List<? extends List> 表示能接收 List 类型及 List 的子类类型
public static void methodB(List<? extends AA> lists) {
for (Object o : lists) {
System.out.println("o.getClass() = " + o.getClass());
}
}
//4. <? super A>表示能接收 A 类型及 A 的父类类型,规定了泛型的上限
//List<? super ArrayList> list 表示能接收 ArrayList 类型及 ArrayList 的父类
public static void methodC(List<? super BB> list) {
for (Object o : list) {
System.out.println("o.getClass() = " + o.getClass());
}
}
}
class AA {
}
class BB extends AA {
}
class CC extends BB {
}
15.7 Junit单元测试
15.7.1 Junit4单元测试概述
- 单元测试就是编写测试代码,可以准确、快速地保证程序的正确性,
Junit
是Java
单元测试的框架。 JUnit4
可以通过注解的方式来标记方法 , 让方法存某种意义 ,常见的注解有:@BeforeClass
全局只会执行一次,而且是第一个运行(标记的方法需要是一个静态无参无返回值方法)@Before
在测试方法运行之前运行(非静态无参无返回值方法)**@Test**
** 测试方法(此方法必须是非静态无参无返回值方法), 主要用于测试的方法 **@After
在测试方法运行之后运行(非静态无参无返回值方法)@AfterClass
全局只会执行一次,而且是最后一个运行(标记的方法需要是一个静态无参无返回值方法)@Ignore
忽略此方法
15.7.2 Junit的基本使用
- 已知存在需要测试的类
Calculator
,这是一个能够简单实现加减乘除、平方、开方的计算器类,然后对这些功能进行单元测试。
public class Calculator {
// 静态变量,用于存储运行结果
private static int result; // 0
// 加法运算
public void add(int n) {
result = result + n;
}
// 减法运算
public void substract(int n) {
// Bug: 正确的应该是 result = result - n
result = result - 1;
}
// 乘法运算
public void multiply(int n) {
// 此方法尚未写好
}
// 除法运算
public void divide(int n) {
result = result / n;
}
// 平方运算
public void square(int n) {
result = n * n;
}
// 平方根运算
public void squareRoot(int n) {
// Bug : 死循环
for (; ;) ;
}
// 将结果清零
public void clear() {
result = 0;
}
// 返回运算结果
public int getResult(){
return result;
}
}
引入 Junit4
的 jar
包到模块中
- 第一步 : 在模块中新建文件夹
lib
,拷贝今天资料中junit4
和hamcrest-core-1.3
的jar
包到模块中 - 第二步 : 选中
jar
文件 , 右键选择Add as Library
生成 Junit
测试框架
- 使用
IDEA
能够直接给需要测试的类生成测试框架,如下:- 选中本类任何位置右键选择
Generate(Alt+Insert)/ go to
选项 , 选择Test...
- 选择需要进行测试的方法
- 在上一步
OK
后系统会自动生成一个新类CalculatorTest
,里面包含一些空的测试用例。
你只需要将这些测试用例稍作修改即可使用,完整的CalculatorTest
代码如下:
- 选中本类任何位置右键选择
package com.heima.junit;
import org.junit.*;
/**
* @author carl
*/
public class CalculatorTest {
static Calculator calculator = new Calculator();
@Before
public void setUp() throws Exception {
}
@After
public void tearDown() throws Exception {
//每次测试完重置结果
System.out.println("测试完成,重置结果");
calculator.clear();
}
@Test
public void add() {
calculator.add(50);
calculator.add(50);
calculator.add(50);
int result = calculator.getResult();
//断言
//Assert.assertEquals(150, result); //通过
}
@Test
public void subtract() {
calculator.add(100);
calculator.subtract(50);
calculator.subtract(50);
calculator.subtract(50);
int result = calculator.getResult();
Assert.assertEquals(-50, result); //Expected :-50 Actual :97
}
@Ignore //不执行
@Test
public void multiply() {
}
@Test
public void divide() {
calculator.divide(0); //java.lang.ArithmeticException: / by zero
int result = calculator.getResult();
Assert.assertEquals(-1, result);
}
@Test
public void square() {
calculator.square(2);
int result = calculator.getResult();
Assert.assertEquals(4, result);
}
@Test(timeout = 3000)
public void squareRoot() {
calculator.squareRoot(9); //超时
int result = calculator.getResult();
Assert.assertEquals(3, result);
}
@Test
public void clear() {
add();
calculator.clear();
int result = calculator.getResult();
Assert.assertEquals(0, result); //通过
}
@Test
public void getResult() {
}
}
限时测试:
对于那些逻辑很复杂,循环嵌套比较深的程序,很有可能出现死循环,因此一定要采取一些预防措施。限时测试是一个很好的解决方案。我们给这些测试函数设定一个执行时间,超过了这个时间,他们就会被系统强行终止,并且系统还会向你汇报该函数结束的原因是因为超时,这样你就可以发现这些 Bug
了。要实现这一功能,只需要给 @Test
标注加一个参数即可,代码如下:
- 被测方法:
public void squareRoot(int n) {
//Bug : 死循环
for (; ; ) ;
}
- 测试方法:
@Test(timeout = 1000)
// Timeout参数表明了你要设定的时间,单位为毫秒,因此1000就代表1秒。
public void squareRoot() {
calculator.squareRoot(4);
assertEquals(2 , calculator.getResult());
}
15.7.3 断言
概述 : 预先判断某个条件一定成立,如果条件不成立,则直接报错。
使用 :
//第一个参数表示期望值
//第二个参数表示实际值
//如果实际值和期望值相同,说明结果正确就测试通过,如果不相同,说明结果是错误的,就会报错
Assert.assertEquals( 期望值, 实际值);
Assert.assertEquals("异常原因", 期望值, 实际值);
//例如:
int result = add(100,200);
Assert.assertEquals(300, result);
小结 : 如何进行断言
Assert.assertEquals(期望值,实际值)
15.7.4 使用案例
package com.hspedu.junit_;
import org.junit.jupiter.api.Test;
/**
* @author: Carl Zhang
* @create: 2021-12-13 16:47
*/
public class JUnit_ {
public static void main(String[] args) {
//传统方法 每次使用就要创建对象,并且注释其他地方
//new JUnit_().method1();
//new JUnit_().method2();
}
@Test //第一次添加@Test会报红,Alt + Enter 弹出提示,选中5.xx版本,点确定自动从仓库下载并配置
public void method1() {
System.out.println("method1被调用");
}
@Test
public void method2() {
System.out.println("method2被调用");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南