1 單元測(cè)試
Junit常用注解(4.幾版本)
@Test |
測(cè)試方法 |
@Before |
用來(lái)修飾實(shí)例方法,該方法會(huì)在每一個(gè)測(cè)試方法執(zhí)行之前執(zhí)行一次。 |
@After |
用來(lái)修飾實(shí)例方法,該方法會(huì)在每一個(gè)測(cè)試方法執(zhí)行之后執(zhí)行一次。 |
@BeforeClass |
用來(lái)靜態(tài)修飾方法,該方法會(huì)在所有測(cè)試方法之前只執(zhí)行一次。 |
@AfterClass |
用來(lái)靜態(tài)修飾方法,該方法會(huì)在所有測(cè)試方法之后只執(zhí)行一次。 |
Junit常用注解(5.幾版本)
@Test |
測(cè)試方法 |
@BeforeEach |
用來(lái)修飾實(shí)例方法,該方法會(huì)在每一個(gè)測(cè)試方法執(zhí)行之前執(zhí)行一次。 |
@AfterEach |
用來(lái)修飾實(shí)例方法,該方法會(huì)在每一個(gè)測(cè)試方法執(zhí)行之后執(zhí)行一次。 |
@BeforeAll |
用來(lái)靜態(tài)修飾方法,該方法會(huì)在所有測(cè)試方法之前只執(zhí)行一次。 |
@AfterAll |
用來(lái)靜態(tài)修飾方法,該方法會(huì)在所有測(cè)試方法之后只執(zhí)行一次。 |
2 反射
反射是在運(yùn)行時(shí)獲取類(lèi)的字節(jié)碼文件對(duì)象,然后可以解析類(lèi)中的全部成分
- 反射的核心思想和關(guān)鍵:得到編譯之后的class文件對(duì)象
- 在運(yùn)行時(shí),可以直接得到這個(gè)類(lèi)的構(gòu)造器對(duì)象Constructor,類(lèi)的成員變量對(duì)象Field,類(lèi)的成員方法對(duì)象Method
這種運(yùn)行時(shí)動(dòng)態(tài)獲取類(lèi)信息以及動(dòng)態(tài)調(diào)用類(lèi)中成分的能力稱(chēng)為Java語(yǔ)言的反射機(jī)制
反射的關(guān)鍵:
反射的第一步都是先獲取Class類(lèi)對(duì)象
// HelloWorld.java -> javac -> HelloWorld.class
// 方式一:類(lèi)名.class
Class c= HelloWorld.class;
// 方式二:Class.forName("全類(lèi)名")
Class c2 = Class.forName("包名.類(lèi)名");
// 方式三:對(duì)象.getClass();
HelloWorld h = new HelloWorld();
Class c3 = h.getClass();
// 獲取類(lèi)的全名,即包名.類(lèi)名
String name = Class.forName("包名.類(lèi)名").getName();
// 只獲取類(lèi)名
String name = Class.forName("包名.類(lèi)名").getSimpleName();
獲取類(lèi)對(duì)象后,我們可以類(lèi)對(duì)象中獲取類(lèi)的成分對(duì)象
獲取構(gòu)造器
方法 | 說(shuō)明 |
Constructor<?>[] getConstructors?() |
返回所有構(gòu)造器對(duì)象的數(shù)組(只能拿public的) |
Constructor<?>[] getDeclaredConstructors?() |
返回所有構(gòu)造器對(duì)象的數(shù)組,存在就能拿到 |
Constructor<T> getConstructor?(Class<?>... parameterTypes) |
返回單個(gè)構(gòu)造器對(duì)象(只能拿public的) |
Constructor<T> getDeclaredConstructor?(Class<?>... parameterTypes) |
返回單個(gè)構(gòu)造器對(duì)象,存在就能拿到 |
Constructor類(lèi)中用于創(chuàng)建對(duì)象的方法
T newInstance?(Object... initargs) |
根據(jù)指定的構(gòu)造器創(chuàng)建對(duì)象 |
public void? setAccessible(boolean flag) |
設(shè)置為true,表示取消訪(fǎng)問(wèn)檢查,進(jìn)行暴力反射 非public的構(gòu)造器,反射可以破壞其封裝性,私有也可以執(zhí)行 |
獲取成員變量
作用:在某個(gè)對(duì)象中取值、賦值
Field[] getFields?() |
返回所有成員變量對(duì)象的數(shù)組(只能拿public的) |
Field[] getDeclaredFields?() |
返回所有成員變量對(duì)象的數(shù)組,存在就能拿到 |
Field getField?(String name) |
返回單個(gè)成員變量對(duì)象(只能拿public的) |
Field getDeclaredField?(String name) |
返回單個(gè)成員變量對(duì)象,存在就能拿到 |
Field類(lèi)中用于取值、賦值的方法
void set?(Object obj, Object value): |
賦值 |
Object get?(Object obj) |
獲取值。 |
獲取方法對(duì)象
作用:在某個(gè)對(duì)象中進(jìn)行執(zhí)行此方法
Method[] getMethods?() |
返回所有成員方法對(duì)象的數(shù)組(只能拿public的) |
Method[] getDeclaredMethods?() |
返回所有成員方法對(duì)象的數(shù)組,存在就能拿到 |
Method getMethod?(String name, Class<?>... parameterTypes) |
返回單個(gè)成員方法對(duì)象(只能拿public的) |
Method getDeclaredMethod?(String name, Class<?>... parameterTypes) |
返回單個(gè)成員方法對(duì)象,存在就能拿到 |
Method類(lèi)中用于觸發(fā)執(zhí)行的方法
Object invoke?(Object obj, Object... args) |
運(yùn)行方法 參數(shù)一:用obj對(duì)象調(diào)用該方法 參數(shù)二:調(diào)用方法的傳遞的參數(shù)(如果沒(méi)有就不寫(xiě)) 返回值:方法的返回值(如果沒(méi)有就不寫(xiě)) |
反射的作用
繞過(guò)編譯階段為集合添加數(shù)據(jù)
反射是在運(yùn)行時(shí)的技術(shù),此時(shí)集合的泛型將不能產(chǎn)生約束了,此時(shí)可以為集合存入其它任意類(lèi)型的元素
ArrayList<Integer> lists = new ArrayList<>();
list.add(100);
// list.add(“ABC"); // 報(bào)錯(cuò)
list.add(99);
// 但是下面方法可以添加字符串
Class l = lists.getClass();
Method add = l.getDeclaredMethod("add", Object.class);
add.invoke(lists, "ABC");
反射的作用:
- 可以在運(yùn)行時(shí)得到一個(gè)類(lèi)的全部成分
- 可以破壞封裝性
- 破壞泛型的約束性
- 做Java高級(jí)框架
基本主流框架都會(huì)基于反射設(shè)計(jì)一些通用技術(shù)功能
3 注解
對(duì)Java中類(lèi)、方法、成員變量做標(biāo)記,然后進(jìn)行特殊處理,到底做何種處理由業(yè)務(wù)需求來(lái)決定
自定義注解
自定義注解就是自己做一個(gè)注解來(lái)使用
public @interface 注解名稱(chēng) {
public 屬性類(lèi)型 屬性名() default 默認(rèn)值 ;
}
元注解
注解的注解,放在注解上的注解
@Target:約束自定義注解只能在哪些地方使用
@Retention:申明注解的生命周期
@Target中可使用的值定義在ElementType枚舉類(lèi)中,常用值如下
- TYPE,類(lèi),接口
- FIELD, 成員變量
- METHOD, 成員方法
- PARAMETER, 方法參數(shù)
- CONSTRUCTOR, 構(gòu)造器
- LOCAL_VARIABLE, 局部變量
@Retention中可使用的值定義在RetentionPolicy枚舉類(lèi)中,常用值如下
- SOURCE: 注解只作用在源碼階段,生成的字節(jié)碼文件中不存在
- CLASS:? 注解作用在源碼階段,字節(jié)碼文件階段,運(yùn)行階段不存在,默認(rèn)值.
- RUNTIME:注解作用在源碼階段,字節(jié)碼文件階段,運(yùn)行階段(開(kāi)發(fā)常用)
注解解析
注解的操作中通常需要進(jìn)行解析,注解的解析就是判斷是否存在注解,存在注解就解析出內(nèi)容
- Annotation:注解的頂級(jí)接口,注解都是Annotation類(lèi)型的對(duì)象
- AnnotatedElement:該接口定義了與注解解析相關(guān)的解析方法
Annotation[]??? getDeclaredAnnotations() |
獲得當(dāng)前對(duì)象上使用的所有注解,返回注解數(shù)組。 |
T getDeclaredAnnotation(Class<T> annotationClass) |
根據(jù)注解類(lèi)型獲得對(duì)應(yīng)注解對(duì)象 |
boolean isAnnotationPresent(Class<Annotation> annotationClass) |
判斷當(dāng)前對(duì)象是否使用了指定的注解,如果使用了則返回true,否則false |
4 動(dòng)態(tài)代理
代理就是被代理者沒(méi)有能力或者不愿意去完成某件事情,需要找個(gè)人代替自己去完成這件事,動(dòng)態(tài)代理就是用來(lái)對(duì)業(yè)務(wù)功能(方法)進(jìn)行代理
關(guān)鍵步驟
必須有接口,實(shí)現(xiàn)類(lèi)要實(shí)現(xiàn)接口(代理通常是基于接口實(shí)現(xiàn))
創(chuàng)建一個(gè)實(shí)現(xiàn)類(lèi)的對(duì)象,該對(duì)象為業(yè)務(wù)對(duì)象,緊接著為業(yè)務(wù)對(duì)象做一個(gè)代理對(duì)象文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-669373.html
優(yōu)點(diǎn)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-669373.html
- 非常靈活,支持任意接口類(lèi)型的實(shí)現(xiàn)類(lèi)對(duì)象做代理,也可以直接為本身做代理
- 可以為被代理對(duì)象的所有方法做代理
- 可以在不改變方法源碼的情況下,實(shí)現(xiàn)對(duì)方法功能的增強(qiáng)
- 不僅簡(jiǎn)化了編程工作、提高了軟件系統(tǒng)的可擴(kuò)展性,同時(shí)也提高了開(kāi)發(fā)效率
// 返回是代理對(duì)象
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
// loader 是定義代理類(lèi)的類(lèi)加載器
// interfaces 代理類(lèi)要實(shí)現(xiàn)的接口列表
// h 代理對(duì)象的核心處理邏輯
public class ProxyUtil {
public static <T> T getProxy(T obj) {
// 返回一個(gè)代理對(duì)象,給別人使用。
// Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
// 參數(shù)一:類(lèi)加載器,負(fù)責(zé)加載代理類(lèi)的
// 參數(shù)二:需要被代理的方法在哪些接口中。
// 參數(shù)三:代理對(duì)象的核心處理邏輯
return (T)Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 核心處理邏輯
// proxy 代理對(duì)象:一般不需要理會(huì)。
// method 代表正在被代理的方法對(duì)象。
// args 被代理方法的參數(shù)值。
// 1、記錄開(kāi)始時(shí)間
long startTime = System.currentTimeMillis();
// 2、觸發(fā)真正的業(yè)務(wù)對(duì)象的方法執(zhí)行。
Object result = method.invoke(obj, args);
// 3、記錄結(jié)束時(shí)間,統(tǒng)計(jì)耗時(shí)
long endTime = System.currentTimeMillis();
System.out.println(method.getName() + "方法耗時(shí):" + (endTime - startTime) / 1000.0 + "s!");
return result; // 4、返回結(jié)果。
}
});
}
}
/**
動(dòng)態(tài)代理需要接口配合。
*/
public interface UserService {
String login(String loginName, String passWord);
void selectUsers();
void deleteUsers();
}
// 創(chuàng)建業(yè)務(wù)對(duì)象
UserService userService = ProxyUtil.getProxy(new UserServiceImpl());
// 調(diào)用方法
String time = userService.login("aaa", "1111")
到了這里,關(guān)于【JAVA】單元測(cè)試、反射、注解、動(dòng)態(tài)代理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!