一.單元測(cè)試
1.1?什么是單元測(cè)試
單元測(cè)試就是針對(duì)最小的功能單元編寫測(cè)試代碼,Java程序最小的功能單元是方法。因此,單元測(cè)試就是針對(duì)Java方法進(jìn)行的測(cè)試,進(jìn)而檢查方法的正確性。
1.2?目前測(cè)試方法是怎么進(jìn)行的
- 只有一個(gè)main方法,如果一個(gè)方法的測(cè)試失敗了,其他測(cè)試方法會(huì)受到影響。
- 無法得到測(cè)試的結(jié)果報(bào)告,需要程序員自己去觀察測(cè)試是否成功。
- 無法實(shí)現(xiàn)自動(dòng)化測(cè)試。
1.3?Junit
Junit概述
JUnit是使用Java語言實(shí)現(xiàn)的單元測(cè)試框架,它是開源的,Java開發(fā)者都應(yīng)當(dāng)學(xué)習(xí)并使用JUnit編寫單元測(cè)試。此外,幾乎所有的IDE工具都集成了JUnit,這樣我們就可以直接在IDE中編寫并運(yùn)行JUnit測(cè)試。
- JUnit可以靈活的選擇執(zhí)行哪些測(cè)試方法,可以一鍵執(zhí)行全部測(cè)試方法。
- Junit可以生成全部方法的測(cè)試報(bào)告。
- 單元測(cè)試中的某個(gè)方法測(cè)試失敗了,不會(huì)影響其他測(cè)試方法的測(cè)試。
1.4?單元測(cè)試快速入門
步驟
第一步:將Junit的jar包導(dǎo)入到項(xiàng)目中。
第二步:編寫測(cè)試方法:該測(cè)試方法必須是公共的無參數(shù)無返回值的非靜態(tài)方法。
第三步:在測(cè)試方法上使用@Test注解,標(biāo)注該方法是一個(gè)測(cè)試方法
第四步:在測(cè)試方法中完成被測(cè)試方法的預(yù)期正確性測(cè)試。
第五步:選中測(cè)試方法,選擇“JUnit運(yùn)行” ,如果測(cè)試良好則是綠色;如果測(cè)試失敗,則是紅色
1.5?Junit常用注解
Junit常用注解(Junit 4.xxxx版本):
Junit常用注解(Junit 5.xxxx版本):
1.6?代碼實(shí)例
二.反射
2.1?反射概述
反射是指對(duì)于任何類,在運(yùn)行的時(shí)候,可以獲取類的字節(jié)碼文件對(duì)象,然后可以解析類中的全部成分。例如,在運(yùn)行時(shí),可以得到:
- 類的構(gòu)造器對(duì)象:Construtor
- 類的成員變量對(duì)象:Field
- 類的成員方法對(duì)象:Method
這種運(yùn)行時(shí)動(dòng)態(tài)獲取類信息以及動(dòng)態(tài)調(diào)用類中成分的能力稱為反射。
2.2?反射的關(guān)鍵
加載完類之后,在堆內(nèi)存的方法區(qū)中就產(chǎn)生了一個(gè)Class類型的對(duì)象,一個(gè)類只有一個(gè)Class對(duì)象,這個(gè)對(duì)象就包含了完整的類的結(jié)構(gòu)信息。我們可以通過這個(gè)對(duì)象看到類的結(jié)構(gòu)。這個(gè)對(duì)象就像一面鏡子,透過這個(gè)鏡子看到類的結(jié)構(gòu),所以,我們形象的稱之為:反射。
- 正常方式:類 =》通過new實(shí)例化 =》取得實(shí)例化對(duì)象
- 反射方式:實(shí)例化對(duì)象 =》getClass()方法 =》得到類完整的結(jié)構(gòu)
反射的第一步都是先得到編譯后的Class文件對(duì)象,然后就可以得到Class的全部成分。
2.3?反射獲取類對(duì)象
獲取Class類的對(duì)象,共有三種方式:
- 方式一:使用Class類中的靜態(tài)方法forName,裝入類,并做類的靜態(tài)初始化,返回Class的對(duì)象代碼格式如下:Class?c1 =?Class.forName("全類名");//全類名就是 src 下的全包名
- 方式二:JVM將使用類加載器,將類加載到內(nèi)存,但前提是類還沒有裝入內(nèi)存,不做類的初始化工作,返回Class的對(duì)象,代碼格式如下:?Class?c2 =?類名.Class;
- 方式三:使用Object類中的getClass方法獲取,會(huì)對(duì)類進(jìn)行靜態(tài)初始化,代碼格式如下:? ? Class?c3 =?對(duì)象.getClass();
2.4?反射獲取構(gòu)造器對(duì)象
步驟:
- 首先得到類對(duì)象
- 通過類對(duì)象獲取構(gòu)造器對(duì)象
- 使用構(gòu)造器對(duì)象創(chuàng)建類的對(duì)象
Class類中用于獲取構(gòu)造器的方法:
Constructor類中用于創(chuàng)建對(duì)象的方法:
作用
獲取構(gòu)造器的作用依然是獲取一個(gè)對(duì)象并返回。
注意事項(xiàng)
如果某個(gè)構(gòu)造器是私有的,那么需要打開權(quán)限(暴力反射),然后再創(chuàng)建對(duì)象。
范例
public class TestDemo {
????//目標(biāo):掌握如何獲取構(gòu)造器對(duì)象,并利用構(gòu)造器對(duì)象創(chuàng)建對(duì)象
????//獲取所有公共的構(gòu)造器對(duì)象
????@Test
????public void getConstructors(){
????????//1.獲得類對(duì)象
????????Class class1 = Student.class;
????????//2.獲得所有公共構(gòu)造器對(duì)象
????????Constructor[] constructors = class1.getConstructors();
????????//3.遍歷構(gòu)造器數(shù)組
????????for (Constructor constructor : constructors) {
????????????System.out.println(constructor.getName()+"===>"+constructor.getParameterCount());
????????}
????}
????//獲取所有的構(gòu)造器對(duì)象,無論構(gòu)造器是公開的,還是私有的
????@Test
????public void getDeclaredConstructors(){
????????//1.獲取類對(duì)象
????????Class class2 = Student.class;
????????//2.獲取所有構(gòu)造器對(duì)象
????????Constructor[] allConstructor = class2.getDeclaredConstructors();
????????//3.遍歷構(gòu)造器對(duì)象
????????for (Constructor constructor : allConstructor) {
????????????System.out.println(constructor.getName()+"===>"+constructor.getParameterCount());
????????}
????}
????//獲取單個(gè)構(gòu)造器對(duì)象
????@Test
????public void getConstructor() throws Exception{
????????//1.獲取類對(duì)象
????????Class class3 = Student.class;
????????//2.獲取單個(gè)構(gòu)造器
????????Constructor constructor = class3.getDeclaredConstructor(String.class,int.class);
????????constructor.setAccessible(true);
????????//3.通過這個(gè)構(gòu)造器創(chuàng)建對(duì)象
????????Student s = (Student) constructor.newInstance("張三",12);
????????System.out.println(s);
????}
????//獲取單個(gè)構(gòu)造器對(duì)象,無視構(gòu)造器的訪問權(quán)限
????@Test
????public void getDeclaredConstructor() throws Exception{
????????//1.獲取類對(duì)象
????????Class class3 = Student.class;
????????//2.獲取單個(gè)構(gòu)造器
????????Constructor constructor = class3.getDeclaredConstructor();
????????//3.暴力反射
????????constructor.setAccessible(true);
????????//4.通過這個(gè)構(gòu)造器創(chuàng)建對(duì)象
????????Student student = (Student) constructor.newInstance();
????????System.out.println(student);
????}
}
2.5?反射獲取成員變量對(duì)象
步驟:
- 首先得到類對(duì)象
- 從類對(duì)象中獲取成員變量對(duì)象
Class類中用于獲取成員變量的方法:
Field中用于取值、賦值的方法
作用
依然是為某個(gè)對(duì)象中對(duì)應(yīng)的成員變量取值和賦值。
注意事項(xiàng)
如果某個(gè)成員變量是私有的,那么需要打開權(quán)限(暴力反射),然后再取值、賦值。
代碼示例
public class FieldDemo1 {
????//目標(biāo):掌握成員變量對(duì)象的獲取,并對(duì)某個(gè)對(duì)象中相應(yīng)的成員變量進(jìn)行取值和賦值
????//通過反射獲取所有成員變量對(duì)象
????@Test
????public void getFields() throws Exception {
????????//1.獲取類對(duì)象
????????Class class1 = Student.class;
????????//2.獲取所有成員變量對(duì)象
????????Field[] fields = class1.getDeclaredFields();
????????//3.遍歷所有成員變量對(duì)象
????????for (Field field : fields) {
????????????System.out.println(field.getName()+"===>"+field.getType());
????????}
????}
????//通過反射獲取一個(gè)成員變量并賦值
????@Test
????public void getField() throws Exception {
????????//1.獲取類對(duì)象
????????Class class1 = Student.class;
????????//2.獲取成員變量對(duì)象
????????Field name = class1.getDeclaredField("name");
????????//3.暴力反射
????????name.setAccessible(true);
????????//4.對(duì)成員變量賦值
????????Student s = new Student();
????????name.set(s,"張三");
????????//5.打印對(duì)象
????????System.out.println(s);
????}
????//通過反射獲取一個(gè)成員變量并取值
????@Test
????public void getField2() throws Exception {
????????//1.獲取類對(duì)象
????????Class class1 = Student.class;
????????//2.獲取成員變量對(duì)象
????????Field name = class1.getDeclaredField("name");
????????//3.暴力反射
????????name.setAccessible(true);
????????//4.對(duì)成員變量取值
????????Student s = new Student("李四",12);
????????String s1 = (String) name.get(s);
????????//5.打印成員變量
????????System.out.println(s1);
????}
}
2.6?反射獲取成員方法對(duì)象
步驟:
- 首先獲取類對(duì)象
- 通過類對(duì)象獲取Method對(duì)象
- 運(yùn)行方法
Class類中用于獲取成員方法的方法:
Method類中用于觸發(fā)執(zhí)行的方法:
作用
獲取成員方法的作用依然是在某個(gè)對(duì)象中執(zhí)行此方法
注意事項(xiàng)
如果某個(gè)成員方法是私有的,那么需要通過暴力反射打開權(quán)限,然后再執(zhí)行此方法。
2.6?反射的作用
2.6.1 繞過編譯階段為集合添加數(shù)據(jù)
反射是作用在運(yùn)行時(shí)的技術(shù),此時(shí)集合的泛型將不能產(chǎn)生約束了,此時(shí)可以為集合存入其他任意類型的元素。
1.原因
泛型只是在編譯階段可以約束集合只能操作某種數(shù)據(jù)類型,在編譯成Class文件進(jìn)入運(yùn)行階段的時(shí)候,其真實(shí)類型都是不帶泛型的集合類型了,泛型相當(dāng)于被擦除了。
2.代碼示例文章來源地址http://www.zghlxwxcb.cn/news/detail-497077.html
2.6.2 通用框架的底層原理
1.需求: 給你任意一個(gè)對(duì)象,在不清楚對(duì)象字段的情況可以把對(duì)象的字段名稱和對(duì)應(yīng)值存儲(chǔ)到文件中去。
文章來源:http://www.zghlxwxcb.cn/news/detail-497077.html
2.代碼示例
//框架代碼:
public class MyBatisUtils {
????public static void save(Object o){
????????try (
????????????????PrintStream ps = new PrintStream(new FileOutputStream("junit-reflect-annotation-proxy/src/reflect.txt",true))
????????????????){
????????????//1.得到類對(duì)象
????????????Class aClass = o.getClass();
????????????ps.println("================="+aClass.getSimpleName()+"=================");
????????????//2.得到類中全部的成員變量對(duì)象
????????????Field[] fields = aClass.getDeclaredFields();
????????????//3.得到全部成員變量對(duì)象的名字和值
????????????for (Field field : fields) {
????????????????field.setAccessible(true);
????????????????String name = field.getName();
????????????????String??value = field.get(o)+" ";
????????????????//4.保存到文件中
????????????????ps.println(name+"---"+value);
????????????}
????????} catch (Exception e) {
????????????e.printStackTrace();
????????}
????}
}
//測(cè)試代碼:
public class ReflectDemo1 {
????public static void main(String[] args) {
????????//目標(biāo):利用反射技術(shù),做一個(gè)通用框架
????????//向?qū)ο笾刑砑訑?shù)據(jù),并將對(duì)象傳到框架中
????????Student s = new Student("張三",17,'男',12,"3000");
????????MyBatisUtils.save(s);
????????Tercher t = new Tercher("張三",17,'男',"王標(biāo)");
????????MyBatisUtils.save(t);
????}
}
到了這里,關(guān)于25.單元測(cè)試、反射的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!