他山之石,可以攻玉。
阅读源码是我们与大师交流的唯一途径,如果放弃了,难道要CRUD到白头吗?
故事也是从这里开始。
起源
观看dubbo官网的时候,在源码导读-服务导出这一节看到一个陌生的Api我十分感兴趣。本着见名知意的原则,猜测了一下大概是判断一个类是否被public修饰符修饰。
发展
查了一下JDK源码对此的解释:
Returns the Java language modifiers for this class or interface, encoded
in an integer复制代码
翻译一下:返回此类或接口的Java语言修饰符,以整数编码的形式。
public class JavaClass{
private final Class abstractPojoClass;
private final Class interFacePojoClass;
public JavaClass(){
abstractPojoClass = AbstractPojo.class;
interFacePojoClass = InterFacePojo.class;
}
public static void main(String[] args){
JavaClass javaClass = new JavaClass();
javaClass.isInterFace();
javaClass.isAbstract();
}
/**
* 判断是否为接口类
*/
private void isInterFace(){
boolean anInterface = interFacePojoClass.isInterface();
boolean isInterface = Modifier.isInterface(interFacePojoClass.getModifiers());
System.out.println(anInterface && isInterface);
}
/**
* 判断是否为抽象类
* fixme: Class貌似没有提供判断方法,需要借助 Modifier
* 同时 {@link Modifier} 提供大量的检测方法
*/
private void isAbstract(){
boolean anAbstract = Modifier.isAbstract(abstractPojoClass.getModifiers());
System.out.println(anAbstract);
}
}
复制代码
结果符合预期:
高潮
抱着好读书,求甚解的态度,我翻开了Modifier的源码。
发现ta的实现十分简短,仅仅使用了一次 & 运算足矣。
public static boolean isInterface(int mod){
return (mod & INTERFACE) != 0;
}
public static boolean isAbstract(int mod){
return (mod & ABSTRACT) != 0;
}
复制代码
然后我又查阅了一下常量的含义。
public static final int ABSTRACT = 0x00000400;
public static final int INTERFACE = 0x00000200;
复制代码
这两个常量就是一个十六进制的数字而已,也没有特殊之处。往上翻了翻:发现Modifier内部定义了大量的常量。而且这些常量都是十六进制八位数,转化成二进制其实就是三十二位。
我还发现了volatile关键字,那可以说明除了Class,Field应该也具备getModifiers()方法。
除此之外我们还见到了眼熟的synchronized关键字,ta可以用来修饰方法。想必Method应该也具备getModifiers()方法。
其实看到这里原理我已经猜出了一个大概。
我的猜想:一定是用0或者1来表示是否,每一位则表示不同的涵义
比如最后一位表示是否被public修饰
倒数第二位表示是否被private修饰
倒数第三位表示是否被protected修饰
我们就用最简单的public来验证我的猜想。
public static boolean isPublic(int mod){
return (mod & PUBLIC) != 0;
}
复制代码
按照源码推算如果被public关键字修饰那么getModifiers()得到的值最后一位必须为1。
public class Test{
public static void main(String[] args){
System.out.println("pojo:" + Integer.toBinaryString(Pojo.class.getModifiers()));
System.out.println("抽象类:" + Integer.toBinaryString(AbstractPojo.class.getModifiers()));
System.out.println("接口:" + Integer.toBinaryString(InterFacePojo.class.getModifiers()));
System.out.println(Integer.toBinaryString(pri.class.getModifiers()));
System.out.println(Integer.toBinaryString(pro.class.getModifiers()));
}
private class pri{
}
protected class pro{
}
}
复制代码
二进制输出得到的值,如果结果前三个是末位是1,且后两个末位不为1方能验证我们的的猜想。
完美符合预期。其实其他的证明方式都一样不妨自己多尝试。
其实原理十分简单,只要熟悉 & 的运算规则即可。
尾声
荆公曾言:世之奇伟、瑰怪、非常之观,常在于险远,而人之所罕至焉,故非有志者不能至也。
愿与诸君互勉之......