第一次写这种探讨类的博客,有很多不懂得地方,也有很多写不好的地方,如果哪里写得不好,恳请你指出;也希望可以留下你的建议,让我努力奋斗一番,看下一次写这种探讨类博客的时候,可以有一定小小的提升,首先感谢你的阅读。
在学习java reflection时,遇上获取与解释修饰符的问题,一直都感到挺迷惑的 — Member.getModifiers()会返回特定的字节码,接着使用Modifier.toString(int mod)来解释此字节码吗mod,会返回修饰符的字符串形式。那这种机制是怎么样实现的呢??为什么要采用这种机制??
对于Member.getModifiers()返回一个特定的字节码,这没有什么好解释的,就是返回一个以特定字节码(十六进制)表示的整数。来看一下如何解释这个特定的字节码,即Modifier.toString(int mod)的实现。
在Modifier类里定义了一系列public静态常量(十六进制)来表示各种修饰符,如下:
public static final int PUBLIC = 0x00000001; public static final int PRIVATE = 0x00000002; public static final int PROTECTED = 0x00000004; public static final int STATIC = 0x00000008; public static final int FINAL = 0x00000010; public static final int SYNCHRONIZED = 0x00000020; public static final int VOLATILE = 0x00000040; public static final int TRANSIENT = 0x00000080; public static final int NATIVE = 0x00000100; public static final int INTERFACE = 0x00000200; public static final int ABSTRACT = 0x00000400; public static final int STRICT = 0x00000800;
可以看到,各个静态常量的值都 是2的几次幂,这样就可以使用逻辑与&操作来判断是否是包含此此常量。如下是Modifier.toString(int mod)的实现:
public static String toString(int mod) {
StringBuffer sb = new StringBuffer();
int len;
if((mod & PUBLIC) != 0) sb.append("public ");
if((mod & PROTECTED) != 0) sb.append("protected ");
if((mod & PRIVATE) != 0) sb.append("private ");
/* 注意以下顺序不能更改 ,在白皮书上指定了下面的顺序*/
if((mod & ABSTRACT) != 0) sb.append("abstract ");
if((mod & STATIC) != 0) sb.append("static ");
if((mod & FINAL) != 0) sb.append("final ");
if((mod & TRANSIENT) != 0) sb.append("transient ");
if((mod & VOLATILE) != 0) sb.append("volatile ");
if((mod & SYNCHRONIZED) != 0) sb.append("synchronized ");
if((mod & NATIVE) != 0) sb.append("native ");
if((mod & STRICT) != 0) sb.append("strictfp ");
if((mod & INTERFACE) != 0) sb.append("interface ");
if((len = sb.length()) > 0) /* 判断是否存在修饰符 */
return sb.toString().substring(0, len-1);
return"";
}
另外说一下的是,在Modifier里一系列(private)静态常量,如下:
static final int BRIDGE = 0x00000040; static final int VARARGS = 0x00000080; static final int SYNTHETIC = 0x00001000; static final int ANNOTATION = 0x00002000; static final int ENUM = 0x00004000;
这些(private)并没有暴露给public的API,要么因为这些(private)常量对于field和method有着不同的含义,而没有其他方式可以区别这两个含义;要么就是因为这些(private)常量并不是java里的关键字。同时可以看一下有关这些(private)常量的函数,如下是Modifier.isSynthetic()的实现:
static boolean isSynthetic(int mod) { return (mod & SYNTHETIC) != 0; }
在Field和Method里的相关函数:
//Field和Method共有的 public boolean isSynthetic() { return Modifier.isSynthetic(getModifiers()); } //Method里的函数 public boolean isBridge() { return (getModifiers() & Modifier.BRIDGE) != 0; } public boolean isVarArgs() { return (getModifiers() & Modifier.VARARGS) != 0; } //Filed里的函数 public boolean isEnumConstant() { return (getModifiers() & Modifier.ENUM) != 0; }
现在来探讨一下为什么采用这种使用特定字节码的来实现获取与解释修饰符。(说明一下,以下都是本人的一些猜想,不一定正确,如果你知道其中一个或几个问题的答案,恳请你可以给出一些参考的建议,万分感谢)
首先因为计算机使用二进制进行运算的,因而直接采用进制形式表达修饰符,有利于提供其运算速度。同时采用特定的字节码,有利于迅速判断包含了哪几种修饰符。
借此延伸想一下,是否可以使用字符串来实现获取与解释修饰符,个人认为这种方法不可取:首先字符串的执行效率远远比不上直接使用二进制代码的执行效率;第二,使用字符串来实现,难以指定各种修饰符的输出顺序。如果使用字符串实现,如何实现呢??如果你知道,希望可以你的参考意见。
那是否可以选择枚举来实现呢??这个本人也在想,感觉可行的样子,可不知道其不足之处在哪里,又是如何去判断包含了哪几个枚举常量??如果你知道其中一个或两个小问题,恳请指导一下小弟,万分感谢。
本文转自peiquan 51CTO博客,原文链接:http://blog.51cto.com/peiquan/1300230