code值獲取內部枚舉類對象(自定義EnumUtil PackageUtil工具類)
項目里,經常涉及到枚舉類的使用。利用反射實現根據枚舉值獲取枚舉對象,可以方便我們對該枚舉對象的直接操作。
通過值實例化枚舉
package com.rq.enumutils.utils;
import com.rq.enumutils.service.EnumMessage;
public class EnumUtil {
/**
* 返回指定編碼的"枚舉"針對實現EnumMessage介面的枚舉類
* @param code
* @return SharedObjTypeEnum
* @throws
*/
public static <T extends EnumMessage> T getEnumBycode(Class<T> clazz, String code) {
for(T inner : clazz.getEnumConstants())
if(code.equals(inner.getCode()))
return inner;
return null;
}
/**
* 返回指定描述的"枚舉"
* @param desc
* @return SharedObjTypeEnum
* @throws
*/
public static <T extends EnumMessage> T getEnumByDesc(Class<T> clazz, String desc) {
for(T inner : clazz.getEnumConstants())
if(inner.getDesc().equals(desc))
return inner;
return null;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
另一種實現方案:在程序啟動時完成所有枚舉類的載入,並填入map集合中(之後操作都從該集合中獲取)
參考地址:https://www.cnblogs.com/jian-xiao/p/6036925.html
package com.rq.enumutils.common;
import com.rq.enumutils.service.EnumMessage;
import com.rq.enumutils.utils.PackageUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 通過code值獲取枚舉對象
* 具體代碼實現:
*
* 1).定義一個EnumMessage介面,然後每個枚舉類實現此介面;
*
* 2).定義常量保存枚舉類所在包名,以及介面全路徑;
*
* 3).在程序啟動時,讀取枚舉類所在包下的所有枚舉類的File文件,在從file文件信息中獲取每個枚舉類的全路徑類名集合A;
*
* 4).遍歷A集合,利用反射獲取每個類的class對象,再判斷該類是否實現了EnumMessage介面;
*
* 5).對於實現了EnumMessage介面的枚舉類,遍歷該枚舉類的所有對象,保存Map<Object, EnumMessage>的集合映射;
*
* 6).對枚舉類保存Map<Class, Map<Object, EnumMessage>>的映射集合。
*/
public class Constant {
/**
* 枚舉類包名集合
*/
public static List<String> pathList = initPackagePathList();
/**
* 枚舉介面類全路徑
*/
public final static String ENUM_MESSAGE_PATH = "com.rq.enumutils.service.EnumMessage";
/**
* 枚舉類對應的全路徑集合
*/
public static final List<String> ENUM_OBJECT_PATH = PackageUtils.getPackageClasses(pathList, true);
/**
* 存放單個枚舉對象 map常量定義
*/
private static Map<Object, EnumMessage> SINGLE_ENUM_MAP = null;
/**
* 所有枚舉對象的 map
*/
public static final Map<Class, Map<Object, EnumMessage>> ENUM_MAP = initialEnumMap(true);
private static List<String> initPackagePathList() {
List<String> list = new ArrayList<>();
list.add("com.rq.enumutils.enums");
return list;
}
/**
* 載入所有枚舉對象數據
*
* @param isFouceCheck 是否強制校驗枚舉是否實現了EnumMessage介面,若為false則沒有實現介面的枚舉類也會被載入
*/
private static Map<Class, Map<Object, EnumMessage>> initialEnumMap(boolean isFouceCheck) {
Map<Class, Map<Object, EnumMessage>> ENUM_MAP = new HashMap<>();
try {
for (String classname : ENUM_OBJECT_PATH) {
Class<?> cls = Class.forName(classname);
//獲取實現的介面列表
Class<?>[] iter = cls.getInterfaces();
boolean flag = false;
if (isFouceCheck) {
for (Class cz : iter) {
//找出實現目標介面的類
if (cz.getName().equals(ENUM_MESSAGE_PATH)) {
flag = true;
break;
}
}
}
if (flag == isFouceCheck) {
//自定義map集合,添加該枚舉類的所有內部枚舉類,
SINGLE_ENUM_MAP = new HashMap<>();
initialSingleEnumMap(cls);
//將新創建的map集合加入到ENUM_MAP集合中
ENUM_MAP.put(cls, SINGLE_ENUM_MAP);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return ENUM_MAP;
}
/**
* 載入每個枚舉對象數據
*/
private static void initialSingleEnumMap(Class<?> cls) throws Exception {
//通過反射調用values方法
Method method = cls.getMethod("values");
EnumMessage inter[] = (EnumMessage[]) method.invoke(null, null);
for (EnumMessage enumMessage : inter) {
SINGLE_ENUM_MAP.put(enumMessage.getCode(), enumMessage);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
介面類
package com.rq.enumutils.service;
public interface EnumMessage {
String getCode();
String getDesc();
}
1
2
3
4
5
6
7
PackageUtils
package com.rq.enumutils.utils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class PackageUtils {
/**
* 返回包下所有的類
*
* @param packagePathList 包名全路徑集合
* @param classWithPath 返回全路徑開關 true 自動帶上包名 false 只返回類名
* @return List<String> 包下所有的類
*/
public static List<String> getPackageClasses(List<String> packagePathList, boolean classWithPath) {
List<String> result = new ArrayList<>();
for(String packagePath : packagePathList) {
List<String> classNames = getClassName(packagePath);
String path = classWithPath ? packagePath + "." : "";
for (String className : classNames) {
//className:com.example.myFirstProject.enums.SexEnum
result.add(path + className.substring(className.lastIndexOf(".") + 1));
}
}
return result;
}
/**
* 獲取該包名全路徑下的所有class全路徑集合
* @param packageName 包名全路徑
* @return
*/
private static List<String> getClassName(String packageName) {
//根據包名獲取該package的系統路徑
String filePath = ClassLoader.getSystemResource("").getPath() + packageName.replace(".", "");
// filePath: /D:/workspace/enumutils/target/classes/com
qenumutilsenums
List<String> classNames = new ArrayList<>();
//注意:區別測試環境與開發環境
List<String> fileNames = getClassName(filePath.replace("test-classes","classes"), classNames);
return fileNames;
}
/**
* 獲取filePath文件夾下的所有class的全路徑集合
* @param filePath
* @param className
* @return
*/
private static List<String> getClassName(String filePath, List<String> className) {
File file = new File(filePath);
File[] childFiles = file.listFiles();
if (childFiles != null) {
for (File childFile : childFiles) {
if (childFile.isDirectory()) {
//遞歸獲取該文件夾下的子文件夾里的所有文件
className.addAll(getClassName(childFile.getPath(), className));
} else {
String childFilePath = childFile.getPath();
//childFilePath: D:workspaceenumutils argetclassescom
qenumutilsenumsSex.class
childFilePath = childFilePath.substring(childFilePath.indexOf("\classes") + 9, childFilePath.lastIndexOf("."));
childFilePath = childFilePath.replace("", ".");
className.add(childFilePath);
}
}
}
return className;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
這裡有個小坑
在getClassName()方法里,如果用tomcat啟動項目,getSystemResource("")會返回空指針
了解 getSystemResource(Stringname)、getSystemResourceAsStream(Stringname)、getSystemResources(Stringname)
內部實現的時候都是用到了ClassLoader system = getSystemClassLoader();的方法,獲取的ClassLoader都是App ClassLoader所以在使用tomcat運行的時候就會取不到classPath路徑下的資源,因為都是WebappClassLoader載入的。詳情點擊:https://www.aliyun.com/jiaocheng/864751.html
解決辦法:
使用當前類.class.getClassLoader().getResource(Stringname)、getResourceAsStream(Stringname)、getResources(Stringname)這三種方法。
工具類EnumUtils
package com.rq.enumutils.utils;
import com.rq.enumutils.common.Constant;
import com.rq.enumutils.service.EnumMessage;
/**
* 獲取內部枚舉類對象
*/
public class EnumUtils {
/**
* 獲取value返回枚舉對象
* @param value 內部枚舉類code值
* @param clazz 需要解析的枚舉類
* */
public static <T extends EnumMessage> T getEnumObject(Object value, Class<T> clazz){
if (value == null || clazz == null) {
return null;
}
return (T) Constant.ENUM_MAP.get(clazz).get(value);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
測試:
@Test
public void contextLoads() {
String line = "佩奇 123 00 03";
String line2 = "米奇 312 01 04";
String line3 = "青霞 111 00 04";
User user = DataUtils.Str2Obj(line, " ", User.class, 0);
User user2 = DataUtils.Str2Obj(line2, " ", User.class, 0);
User user3 = DataUtils.Str2Obj(line3," ",User.class,0);
System.out.println("user1:---"+user);
System.out.println("user2:---"+user2);
System.out.println("user3:---"+user3);
}
1
2
3
4
5
6
7
8
9
10
11
12
輸出:
實例下載:https://download.csdn.net/download/qq_41981107/10859325
---------------------
作者:咚咚大帝
原文:https://blog.csdn.net/qq_41981107/article/details/85053821
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
TAG:程序員小新人學習 |