前言
本文主要介绍Java中Junit、注解、枚举的概念。
一、Junit单元测试
软件测试的目的:软件开发的目的是交付给用户一个正确、稳定的项目,为了保证项目的稳定性,我们就需要对代码进行测试之后再上线进而交付给用户;
测试的分类:测试分为黑盒测试和白盒测试,其中黑盒测试仅仅在软件功能层面对我们的代码进行测试(不关注代码逻辑),而白盒测试需要写代码,对项目代码进行测试。
1.引入Junit
如果需要对业务代码进行测试一定要在main方法(程序的入口)进行;
测试的逻辑如果要分开的话,需要定义多个测试类或者测试方法,比较麻烦;
业务代码
package com.zhanggen.calcaulator; public class Calculator { //加法 public int add(int a, int b) { return a + b; } //减法 public int sub(int a, int b) { return a - b; } }
--------------------------
测试代码
package com.zhanggen.calcaulator; import java.util.Calendar; public class test { public static void main(String[] args) { //测试计算器的功能 Calculator cal = new Calculator(); //测试加法逻辑 int result = cal.add(10, 10); System.out.println(result); //测试减法逻辑 int resuit2 = cal.sub(20, 10); System.out.println(resuit2); } }
2.使用junit
使用junit,我们可以在不使用main方法的情况下独立运行Java类中定义的所有方法;
---------------
package com.zhanggen.test; import com.zhanggen.calcaulator.Calculator; import org.junit.Assert; import org.junit.Test; public class CalculatorTest { //测试add方法 @Test public void testAdd() { //测试add方法 Calculator cal = new Calculator(); int result = cal.add(10, 20); //加入断言:判断一下我预测的结果和实际的计算出来的结果是否一致? Assert.assertEquals(30, result); } //测试sub减法 @Test public void testSub() { //测试sub方法 Calculator cal = new Calculator(); int result = cal.sub(30, 20); //加入断言:判断一下我预测的结果和实际的结果是否一致? Assert.assertEquals(10, result); } }
3.@Before和@After注解
在某一个方法中,加入@Before注解之后,那么该方法中的功能,会在测试方法执行前执行;通常用于申请资源;
在某一个方法中,加入@After注解之后,那么该方法中的功能,会在测试方法执行后执行;通常用于释放申请的资源;
package com.zhanggen.test; import com.zhanggen.calcaulator.Calculator; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; public class CalculatorTest { @Before public void start() { System.out.println("申请资源"); } @After public void end() { System.out.println("释放资源"); } //测试add方法 @Test public void testAdd() { //测试add方法 Calculator cal = new Calculator(); int result = cal.add(10, 20); //加入断言:判断一下我预测的结果和实际的计算出来的结果是否一致? Assert.assertEquals(30, result); System.out.println("执行add方法的测试!"); } //测试sub减法 @Test public void testSub() { //测试sub方法 Calculator cal = new Calculator(); int result = cal.sub(30, 20); //加入断言:判断一下我预测的结果和实际的结果是否一致? Assert.assertEquals(10, result); System.out.println("执行sub方法的测试!"); } }
二、反射
反射是Java提供的一套动态执行API,Java框架底层都是使用反射实现的;
动态功能的软件都是利用反射实现的,软件在执行前,不知道类型,不知道方法名,需要使用反射实现;
1.反射是什么?
反射是Java提供的一套动态执行API。
2.反射的功能
动态根据类名加载类到内容
动态根据类型创建对象
动态访问属性和方法
动态打开访问权限,访问被private修饰的属性和方法
3.获取类API
我们使用c小写的class定义类,使用C大写的Class代表反射获取的对象;
方式1:Class.forName("类名"),根据类名动态获取Class对象,适合根据动态给定的类名,创建Class对象;
package com.company; import java.util.Scanner; public class Demo01 { public static void main(String[] args) throws Exception { //利用Class.forName()动态获取类 System.out.printf("请输入类名:"); Scanner sc = new Scanner(System.in); String className = sc.next().trim(); Class cls = Class.forName(className); System.out.println(cls); } }
方式2:类型.class属性获取Class对象,适合直接根据类名获得Class对象;
package com.company; import java.io.File; public class Demo02 { public static void main(String[] args) { /* Java所有类型都有1个默认属性 .class; 是静态获得类型,不能体现动态性; */ Class cls = String.class; cls = int.class; cls = File.class; cls = Foo.class; System.out.println(cls); } }
方式3:对象.getClass()获得对象的类型,适合已经存在的对象;
package com.company; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Demo03 { public static void main(String[] args) { /* 在Java中所有对象都包含1个.getClass()方法; 利用对象的getClass方法,获取对象的类型,该方法经常于动态检查某个对象的类型; * */ Class cls = "ok".getClass(); //class java.lang.String cls = new Integer(2390).getClass(); //class java.lang.Integer cls = System.in.getClass(); //class java.io.BufferedInputStream cls = System.out.getClass(); //class java.io.PrintStream System.out.println(cls.getClass()); List<String> list = new ArrayList<>(); Iterator<String> i = list.iterator(); System.out.println(i.getClass()); //class java.util.ArrayList$Itr $代表Itr是ArrayList的内部类 list = new LinkedList<>(); Iterator<String> i1 = list.iterator(); System.out.println(i1.getClass()); } }
4.根据类名创建对象API
package com.company; import java.util.Scanner; public class Demo04 { public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); System.out.print("请输入类名:"); //动态加载Class对象 String className = sc.nextLine().trim(); Class cls = Class.forName(className); //之前是静态的,现在动态创建对象; Object obj = cls.newInstance(); System.out.println(obj); } }
5.访问对象的属性
package com.company; import java.lang.reflect.Field; public class Demo05 { public static void main(String[] args) throws Exception { String className = "com.company.Foo"; Class cls = Class.forName(className); //获取所有属性列表 Field[] fieldList = cls.getDeclaredFields(); //跟属性名称获取单个属性 Field name = cls.getDeclaredField("name"); System.out.println(name); //获取所有属性 for (Field field : fieldList) { System.out.println(field); } } }
6.获取字段的值
通过反射可以获取 对象的属性值也可以修改对象的属性值;
package com.company; import java.lang.reflect.Field; public class Demo06 { //动态获取对象字段的值 public static void main(String[] args) throws Exception { //根据字符串获取类 Class cls = Class.forName("com.company.Foo"); //类实例化出1个对象 Object obj = cls.newInstance(); //获取name字段并获取该字段的值 Field nameField = cls.getDeclaredField("name"); Object nameValue = nameField.get(obj); System.out.println((String) nameValue); //获取age字段并获取该字段的值 Field ageField = cls.getDeclaredField("age"); Object ageValue = ageField.get(obj); System.out.println((int) ageValue); //获取私有字段的值 Field salaryField = cls.getDeclaredField("salary"); //由于salary字段是私有属性,所以反射在获取其属性值时必须夺权; salaryField.setAccessible(true); Object salaryValue = salaryField.get(obj); System.out.println((long) salaryValue); //------------修改对象的属性----------------------// salaryField.set(obj,99999999); salaryValue = salaryField.get(obj); System.out.println((long) salaryValue); } }
7.动态执行方法
使用反射API可以动态获取并执行对象的方法;
package com.company; import java.lang.reflect.Method; public class Demo07 { public static void main(String[] args) throws Exception { String className = "com.company.Foo"; Class cls = Class.forName(className); //查询所有的方法 Method[] methodArray = cls.getDeclaredMethods(); for (Method method : methodArray) { System.out.println(method); } //根据方法名称获取方法:方法名称和方法参数类型 Method method = cls.getDeclaredMethod("walk", String.class); System.out.println(method); //执行方法 Object obj = cls.newInstance(); method.invoke(obj, "光明路"); //获取私有方法 Method hugeMethod = cls.getDeclaredMethod("huge", String.class); hugeMethod.setAccessible(true); System.out.println(method); //执行私有方法 hugeMethod.invoke(obj, "光明"); } }
三、注解(annotation)
注解是Java 5开始提供的新语法,用于为程序添加附件功能;
注解和反射的联系非常密切,在软件运行期间利用反射API,查找到注解,根据注解信息添加附件功能;
Java很多框架底层都是利用 注解+反射机制,实现框架的功能附加功能的;
1.注解使用流程
(1).定义注解
(2).在类/字段/属性/方法上标注注解
(3).在软件运行期间利用反射API,查找注解,根据注解信息添加附件功能;
2.注解传播范围