日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java測試動態方法_java反射学习

發(fā)布時(shí)間:2023/12/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java測試動態方法_java反射学习 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

反射的核心Class類

Class類是一個(gè)特殊的類,不能手動(dòng)創(chuàng)建,只能由jvm來創(chuàng)建。 jvm在類加載時(shí)會(huì)為每個(gè)類生成一個(gè)與之對(duì)應(yīng)的Class對(duì)象在Java堆中(且每個(gè)類只會(huì)有一個(gè)對(duì)應(yīng)的Class對(duì)象),用來保存該類的結(jié)構(gòu)信息。該類的對(duì)象都要通過這個(gè)Class對(duì)象來進(jìn)行實(shí)例化。

可以通過Class的對(duì)象來獲得該類的結(jié)構(gòu)信息(構(gòu)造器、方法、屬性等)。

反射是什么

JAVA反射機(jī)制是在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)實(shí)體類,都能夠知道這個(gè)類的所有屬性和方法;對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意方法和屬性;這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象方法的功能稱為java語(yǔ)言的反射機(jī)制。

Class對(duì)象就像是一面鏡子,我們并不能直接得到加載的類里的內(nèi)容,而是需要通過Class對(duì)象這面鏡子反射內(nèi)部的信息來得到的。

通過Class對(duì)象來獲得類的結(jié)構(gòu)信息并且把各個(gè)結(jié)構(gòu)部分分別映射成各個(gè)對(duì)象這個(gè)過程就是反射了。

如何獲得Class對(duì)象

創(chuàng)建一個(gè)User類來進(jìn)行測(cè)試

package com.rainc.test.bean;

/**

* @Author rainc

* @create 2019/10/12 19:51

*/

public class User {

private int id;

private int age;

private String name;

public User() {

}

public User(int id, int age, String name) {

this.id = id;

this.age = age;

this.name = name;

}

public int getId() {

return id;

}

public void setId(int id) {

this.id = id;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

}

public static void main(String[] args) {

User user=new User();

//1.通過該類的對(duì)象直接過得Class對(duì)象

Class clz=user.getClass();

System.out.println(clz);

//2.通過類.class獲得

clz=User.class;

System.out.println(clz);

//3.調(diào)用Class的靜態(tài)方法forName通過類全名來獲得

try {

String path = "com.rainc.test.bean.User";

clz = Class.forName(path);

System.out.println(clz);

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

}

Snipaste_2019-10-19_16-43-41.png

通過反射api來獲得類的結(jié)構(gòu)信息

public static void main(String[] args) {

String path = "com.rainc.test.bean.User";

try {

Class clz = Class.forName(path);

//獲取類的名字

System.out.println(clz.getName());//獲得類全名

System.out.println(clz.getSimpleName());//獲得類名

//獲取屬性信息

Field[] fields = clz.getFields();//只能獲得public的field

for (Field temp : fields) {

System.out.println("屬性:" + temp);

}

fields = clz.getDeclaredFields();//獲得所有的field

for (Field temp : fields) {

System.out.println("屬性:" + temp);

}

//獲得指定的屬性信息

Field f = clz.getDeclaredField("name");

//獲取方法信息

Method[] methods = clz.getDeclaredMethods();

//通過名字獲取指定的方法信息

//獲得無參的指定方法

for (Method temp : methods) {

System.out.println("方法:" + temp);

}

Method m1 = clz.getDeclaredMethod("getName");

//獲得有參的指定方法

Method m2 = clz.getDeclaredMethod("setName", String.class);

//獲得構(gòu)造器信息

Constructor[] constructors = clz.getDeclaredConstructors();

//獲得無參的構(gòu)造器

Constructor c = clz.getDeclaredConstructor();

//獲得有參的構(gòu)造器

c = clz.getDeclaredConstructor(int.class, int.class, String.class);

} catch (Exception e) {

e.printStackTrace();

}

}

Snipaste_2019-10-20_09-33-17.png

通過反射api動(dòng)態(tài)的操作構(gòu)造器、方法、屬性

public static void main(String[] args) {

String path = "com.rainc.test.bean.User";

try {

Class clz = (Class) Class.forName(path);

//獲得構(gòu)造器信息

//通過反射api調(diào)用構(gòu)造方法,構(gòu)造對(duì)象

clz.getDeclaredConstructor().newInstance();

//通過反射api調(diào)用普通方法

User u = clz.getDeclaredConstructor().newInstance();

Method method = clz.getDeclaredMethod("setName", String.class);

method.invoke(u, "rainc");//相當(dāng)于 u.setName("rainc")

System.out.println(u.getName());

//通過反射api操作屬性

User u2 = clz.getDeclaredConstructor().newInstance();

Field f = clz.getDeclaredField("name");

f.setAccessible(true);//解除安全檢查,可以通過這個(gè)方法使用私有方法和屬性等

f.set(u2, "rainc2");

System.out.println(u2.getName());

} catch (Exception e) {

e.printStackTrace();

}

}

Snipaste_2019-10-20_09-36-19.png

反射的效率

使用反射的效率會(huì)比直接通過對(duì)象調(diào)用方法效率低。通過setAccessible(true)方法解除安全檢查可以提高反射的運(yùn)行效率

創(chuàng)建TestBean類用來測(cè)試

/**

* @Author rainc

* @create 2019/10/20 9:19

*/

public class TestBean {

long sum=0;

public long getSum() {

return sum;

}

public void setSum(int sum) {

this.sum+=sum;

}

}

創(chuàng)建Test類進(jìn)行測(cè)試

import java.lang.reflect.Method;

/**

* @Author rainc

* @create 2019/10/20 9:19

*/

public class TestAccessiable {

public static void main(String[] args) throws Exception {

test01();

test02();

test03();

}

/**

* 普通方法

*/

public static void test01() {

TestBean t=new TestBean();

long startTtime = System.currentTimeMillis();

for (int i = 0; i < 1000000000L; i++) {

t.setSum(i);

}

System.out.println("和:"+t.getSum());

long endTime = System.currentTimeMillis();

System.out.println("普通方法調(diào)用10億次耗時(shí):" + (endTime - startTtime) + "ms");

}

/**

* 反射調(diào)用

*/

public static void test02() throws Exception {

TestBean t=new TestBean();

Class clz=t.getClass();

Method m=clz.getDeclaredMethod("setSum", int.class);

long startTtime = System.currentTimeMillis();

for (int i = 0; i < 1000000000L; i++) {

m.invoke(t,i);

}

System.out.println("和:"+t.getSum());

long endTime = System.currentTimeMillis();

System.out.println("反射調(diào)用10億次耗時(shí):" + (endTime - startTtime) + "ms");

}

/**

* 解除安全檢查,反射調(diào)用

*/

public static void test03() throws Exception {

TestBean t=new TestBean();

Class clz=t.getClass();

Method m=clz.getDeclaredMethod("setSum", int.class);

m.setAccessible(true);

long startTtime = System.currentTimeMillis();

for (int i = 0; i < 1000000000L; i++) {

m.invoke(t,i);

}

System.out.println("和:"+t.getSum());

long endTime = System.currentTimeMillis();

System.out.println("解除安全檢查,反射調(diào)用10億次耗時(shí):" + (endTime - startTtime) + "ms");

}

}

Snipaste_2019-10-20_09-43-18.png

可以看出,普通的方法調(diào)用效率最高,其次是解除安全檢查的,效率最低的是直接通過反射調(diào)用。

盡管反射的效率并不如普通的方法調(diào)用,但是由于其擁有動(dòng)態(tài)性,在框架中有著大量的使用,而這些框架卻能大大的提高我們的工作效率。因此犧牲一定的性能效率來提高工作效率也是必要的。

反射操作泛型

ParameterizedType:表示一種參數(shù)化的類型,比如Collection< String >(常用)

GenericArrayType:表示一種元素類型是參數(shù)化類型或者類型變量的數(shù)組類型

TypeVariable:是各種類型變量的公共父接口

WildcardType:代表一種通配符類型表達(dá)式,比如?、? extends Number、? super Integer。(wildcard是一個(gè)單詞:就是”通配符“)

import com.rainc.test.bean.User;

import java.lang.reflect.Method;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

import java.util.List;

import java.util.Map;

/**

* @Author rainc

* @create 2019/10/20 10:10

*/

public class TestGenericity {

public void test01(Map map, List list){

}

public Map test02(){

return null;

}

public static void main(String[] args) throws Exception {

Class clz=TestGenericity.class;

//獲得指定方法的泛型

System.out.println("獲得指定方法的泛型");

Method m=clz.getMethod("test01", Map.class, List.class);

//取得方法的所有參數(shù)類型

Type[] t=m.getGenericParameterTypes();

for (Type paramType:t){

System.out.println("#"+paramType);

//判斷取得的參數(shù)是否為參數(shù)化類型

if (paramType instanceof ParameterizedType){

//是的話將其強(qiáng)制轉(zhuǎn)型并獲得泛型的真正類型

Type[] genericTypes=((ParameterizedType) paramType).getActualTypeArguments();

for (Type genericType:genericTypes){

System.out.println("泛型類型:"+genericType);

}

}

}

//獲得指定方法返回值泛型

System.out.println("\n\n指定方法返回值泛型");

Method m2=clz.getMethod("test02");

//由于返回值只會(huì)有一個(gè)因此不需要數(shù)組

Type returnType =m2.getGenericReturnType();

if (returnType instanceof ParameterizedType){

Type[] genericTypes=((ParameterizedType) returnType).getActualTypeArguments();

for (Type genericType:genericTypes){

System.out.println("泛型類型:"+genericType);

}

}

}

}

Snipaste_2019-10-20_10-47-16.png

總結(jié)

以上是生活随笔為你收集整理的java測試動態方法_java反射学习的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。