在系统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舒服!