反射處理java泛型
來源:易賢網(wǎng) 閱讀:1943 次 日期:2015-04-10 14:14:37
溫馨提示:易賢網(wǎng)小編為您整理了“反射處理java泛型”,方便廣大網(wǎng)友查閱!

當(dāng)我們聲明了一個(gè)泛型的接口或類,或需要一個(gè)子類繼承至這個(gè)泛型類,而我們又希望利用反射獲取這些泛型參數(shù)信息。這就是本文將要介紹的ReflectionUtil就是為了解決這類問題的輔助工具類,為java.lang.reflect標(biāo)準(zhǔn)庫的工具類。它提供了便捷的訪問泛型對象類型(java.reflect.Type)的反射方法。

本文假設(shè)你已經(jīng)了解java反射知識(shí),并能熟練的應(yīng)用。如果還不了解java反射知識(shí),那么你可以先移步到Oracel反射課程,這可能是你開始學(xué)習(xí)反射的好起點(diǎn).

ReflectionUtil中包含以下幾種功能:

通過Type獲取對象class;

通過Type創(chuàng)建對象;

獲取泛型對象的泛型化參數(shù);

檢查對象是否存在默認(rèn)構(gòu)造函數(shù);

獲取指定類型中的特定field類型;

獲取指定類型中的特定method返回類型;

根據(jù)字符串標(biāo)示獲取枚舉常量;

ReflectionUtil下載地址.

通過Type獲取對象class

private static final String TYPE_NAME_PREFIX = "class ";

public static String getClassName(Type type) {

if (type==null) {

return "";

}

String className = type.toString();

if (className.startsWith(TYPE_NAME_PREFIX)) {

className = className.substring(TYPE_NAME_PREFIX.length());

}

return className;

}

public static Class<?> getClass(Type type)

throws ClassNotFoundException {

String className = getClassName(type);

if (className==null || className.isEmpty()) {

return null;

}

return Class.forName(className);

}

方法ReflectionUtil#getClass(Type)實(shí)現(xiàn)了從java.lang.reflect.Type獲取java.lang.Class對象名稱。這里利用了Type的toString方法獲取所在類型的class。如“class some.package.Foo”,截取后部分class名稱,在利用Class.forName(String)獲取class對象。

通過Type創(chuàng)建對象

public static Object newInstance(Type type)

throws ClassNotFoundException, InstantiationException, IllegalAccessException {

Class<?> clazz = getClass(type);

if (clazz==null) {

return null;

}

return clazz.newInstance();

}

方法ReflectionUtil#newInstance(Type type)實(shí)現(xiàn)根據(jù)Type構(gòu)造對象實(shí)例。在這里輸入的Type不能是抽象類、接口、數(shù)組類型、以及基礎(chǔ)類型、Void否則會(huì)發(fā)生InstantiationException異常。

獲取泛型對象的泛型化參數(shù)

首先假設(shè)我們有如下兩個(gè)對象:

public abstract class Foo<T> {

//content

}

public class FooChild extends Foo<Bar> {

//content

}

怎么獲取子類在Foo中傳入的泛型Class類型呢?

比較常用的做法有以下兩種:

強(qiáng)制FooChild傳入自己的class類型(這也是比較常用的做法):

public abstract class Foo<T> {

private Class<T> tClass;

public Foo(Class<T> tClass) {

this.tClass = tClass;

}

//content

}

public class FooChild extends Foo<Bar> {

public FooChild() {

super(FooChild.class);

}

//content

}

利用反射獲取:

public static Type[] getParameterizedTypes(Object object) {

Type superclassType = object.getClass().getGenericSuperclass();

if (!ParameterizedType.class.isAssignableFrom(superclassType.getClass())) {

return null;

}

return ((ParameterizedType)superclassType).getActualTypeArguments();

}

方法ReflectionUtil#getParameterizedTypes(Object)利用反射獲取運(yùn)行時(shí)泛型參數(shù)的類型,并數(shù)組的方式返回。本例中為返回一個(gè)T類型的Type數(shù)組。

為了Foo得到T的類型我們將會(huì)如下使用此方法:

...

Type[] parameterizedTypes = ReflectionUtil.getParameterizedTypes(this);

Class<T> clazz = (Class<T>)ReflectionUtil.getClass(parameterizedTypes[0]);

...

注意:

在java.lang.reflect.ParameterizedType#getActualTypeArguments() documentation:的文檔中你能看見如下文字:

in some cases, the returned array can be empty. This can occur. if this type represents

a non-parameterized type nested within a parameterized type.

當(dāng)傳入的對象為非泛型類型,則會(huì)返回空數(shù)組形式。

檢查對象是否存在默認(rèn)構(gòu)造函數(shù)

public static boolean hasDefaultConstructor(Class<?> clazz) throws SecurityException {

Class<?>[] empty = {};

try {

clazz.getConstructor(empty);

} catch (NoSuchMethodException e) {

return false;

}

return true;

}

方法ReflectionUtil#hasDefaultConstructor利用java.lang.reflect.Constructor檢查是否存在默認(rèn)的無參構(gòu)造函數(shù)。

獲取指定類型中的特定field類型

public static Class<?> getFieldClass(Class<?> clazz, String name) {

if (clazz==null || name==null || name.isEmpty()) {

return null;

}

name = name.toLowerCase();

Class<?> propertyClass = null;

for (Field field : clazz.getDeclaredFields()) {

field.setAccessible(true);

if (field.getName().equals(name)) {

propertyClass = field.getType();

break;

}

}

return propertyClass;

}

在某些情況下你希望利用已知的類型信息和特定的字段名字想獲取字段的類型,那么ReflectionUtil#getFieldClass(Class<?>, String)可以幫助你。ReflectionUtil#getFieldClass(Class<?>, String) 利用Class#getDeclaredFields()獲取字段并循環(huán)比較java.lang.reflect.Field#getName()字段名稱,返回字段所對應(yīng)的類型對象。

獲取指定類型中的特定method返回類型

public static Class<?> getMethodReturnType(Class<?> clazz, String name) {

if (clazz==null || name==null || name.isEmpty()) {

return null;

}

name = name.toLowerCase();

Class<?> returnType = null;

for (Method method : clazz.getDeclaredMethods()) {

if (method.getName().equals(name)) {

returnType = method.getReturnType();

break;

}

}

return returnType;

}

方法ReflectionUtil#getMethodReturnType(Class<?>, String)可以幫助你根據(jù)對象類型和方法名稱獲取其所對應(yīng)的方法返回類型。ReflectionUtil#getMethodReturnType(Class<?>, String)利用Class#getDeclaredMethods()并以java.lang.reflect.Method#getName()比對方法名稱,返回找到的方法的返回值類型(Method#getReturnType()).

根據(jù)字符串標(biāo)示獲取枚舉常量

@SuppressWarnings({ "unchecked", "rawtypes" })

public static Object getEnumConstant(Class<?> clazz, String name) {

if (clazz==null || name==null || name.isEmpty()) {

return null;

}

return Enum.valueOf((Class<Enum>)clazz, name);

}

方法ReflectionUtil#getEnumConstant(Class<?>, String)為利用制定的枚舉類型和枚舉名稱獲取其對象。這里的名稱必須和存在的枚舉常量匹配。

更多信息請查看IT技術(shù)專欄

更多信息請查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:反射處理java泛型
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺(tái) | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網(wǎng)安備53010202001879號 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)