在系统API中,通常会定义一些int类型的静态变量,用于表示一些类型,而我们得到一个int值时,我想知道这个值对应的是哪个类型,就需要拿这个值去静态变量那里比较,很是麻烦,所以就想通过反射得到所有的静态变量,然后用代码帮我找出那个对应的变量名,示例如下:
- public class MediaType {
- public static int MP3 = 0x2348;
- public static int MP4 = 0x2315;
- public static int AVI = 0x4356;
- }
-
如上代码,定义了一些多媒体类型,然后我们通过API获取到了一个具体的类型,如下:
- int type = mPlayer.getFileMediaType(file);
-
如上代码,我们得到了一个文件类型,但是它是int类型,需要去Type中对比才能知道它具体是哪一个类型,这就很麻烦了,如果Type 中定义的变量非常多,找起来就麻烦了,而且他是用16进制写的,但是我们拿到的type肯定是十进制的,还要转换为16进制,再去Type中对比查找,虽然可以使用搜索功能,但还是挺麻烦的,所以想要使用代码来帮我们找出这个type值对应的属性名称。
关键代码:
实现代码如下:
- public class MediaType {
- public static int MP3 = 0x2348;
- public static int MP4 = 0x2315;
- public static int AVI = 0x4356;
- }
-
- public class Test {
-
- public static void main(String[] args) {
- Map<Integer, String> fieldMap = getAllPublicStaticIntField(MediaType.class);
- for (Map.Entry<Integer, String> entry : fieldMap.entrySet()) {
- System.out.println(entry.getKey() + " : " + entry.getValue());
- }
- }
-
- public static Map<Integer, String> getAllPublicStaticIntField(Class<?> clazz) {
- Map<Integer, String> fieldsMap = new HashMap<>();
- try {
- Field[] fields = clazz.getFields();
- for (Field field : fields) {
- int modifiers = field.getModifiers();
- boolean isPublic = Modifier.isPublic(modifiers);
- boolean isStatic = Modifier.isStatic(modifiers);
- boolean isInt = field.getGenericType() == int.class;
- if (isPublic && isStatic && isInt) {
- fieldsMap.put((Integer) field.get(null), field.getName());
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return fieldsMap;
- }
-
- }
-
输出结果如下:
- 8981 : MP4
- 17238 : AVI
- 9032 : MP3
-
OK,三个静态变量都拿到了,当我们得到一个type值为8981,我们不用自己去代码中对比它是哪个类型的值了,直接用代码打印出来即可,如下:
- public static void main(String[] args) {
- int type = 8981;
- String fieldName = getAllPublicStaticIntField(MediaType.class).get(type);
- System.out.println(type + " is " + fieldName);
- }
-
输出如下:
- 8981 is MP4
-
注:我发现一个Bug,当我把变量的值设置为0时,则只能获取到一个变量,示例如下:
- public class MediaType {
- public static int MP3 = 0;
- public static int MP4 = 0;
- public static int AVI = 0;
- }
-
- public class Test {
-
- public static void main(String[] args) {
- Map<Integer, String> fieldMap = getAllPublicStaticIntField(MediaType.class);
- for (Map.Entry<Integer, String> entry : fieldMap.entrySet()) {
- System.out.println(entry.getKey() + " : " + entry.getValue());
- }
- }
-
- public static Map<Integer, String> getAllPublicStaticIntField(Class<?> clazz) {
- Map<Integer, String> fieldsMap = new HashMap<>();
- ...
- return fieldsMap;
- }
-
- }
-
输出如下:
- 0 : AVI
-
不知道这是不是系统bug,如果不是系统bug而是因为我的水平有限无法理解这个异常,请知道原因的朋友告诉我一下这是怎么回事。
后续:大意了,发现原因了,这属于java基础的问题,因为三个变量都是0的话,存到map集合中时,key都是0就重复了,当key是一样时,则后面存进来的会把前面的覆盖,所以最终只保存到了一个变量。
- object ReflectUtil {
-
- /** 获取指定类中的所有public static int类型的变量 */
- fun getAllPublicStaticIntField(clazz: Class<*>): Map<Int, String> {
- val fieldsMap: MutableMap<Int, String> = HashMap()
- clazz.fields.filter {
- Modifier.isPublic(it.modifiers) && Modifier.isStatic(it.modifiers) && it.genericType === Int::class.javaPrimitiveType
- }.forEach {
- fieldsMap[it.get(null) as Int] = it.name
- }
- return fieldsMap
- }
-
- /** 返回指定的值对应的是指定类的哪个变量,如果没有对应的变量,则返回value自身 */
- fun getPublicStaticIntFieldNameByValue(clazz: Class<*>, value: Int): String {
- return getAllPublicStaticIntField(clazz)[value] ?: value.toString()
- }
- }
-
- fun main() {
- println(ReflectUtil.getPublicStaticIntFieldNameByValue(MediaType::class.java, 8981))
- }
-
Kotlin就是爽啊,这代码写起来就是比Java舒服!