您当前的位置:首页 > 计算机 > 编程开发 > Java

Java通过反射获取指定类型的变量

时间:02-05来源:作者:点击数:

Java版本实现

在系统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值对应的属性名称。

关键代码:

  • Modifier.isPublic(field.getModifiers()) 判断是否是public
  • Modifier.isStatic(field.getModifiers()) 判断是否是static
  • field.getGenericType() 获取变量类型

实现代码如下:

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是一样时,则后面存进来的会把前面的覆盖,所以最终只保存到了一个变量。

Kotlin版本实现

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舒服!

方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门