Modifier 修饰符工具类
public class java.lang.reflect.Modifier extends Object
int java.lang.reflect.Field.getModifiers()
以整数形式返回此 Method 对象所表示方法的 Java 语言修饰符
boolean java.lang.reflect.Modifier.isPublic(int mod)
如果整数参数包括 public 修饰符,则返回 true,否则返回 false。其他方法类似
方法的修饰符获取与属性类似
JDK中的介绍:
Modifier 类提供了 static 方法和常量,对类和成员访问修饰符进行解码。修饰符集被表示为整数,用不同的位位置 (bit position) 表示不同的修饰符。表示修饰符的常量值取自于 The JavaTM Virtual Machine Specification, Second edition 的表 4.1、4.4、4.5 和 4.7。
解码方法
以上所有的修饰符都有对应的、方法声明为【public static boolean is***(int mod)】的解码方法,且方法的实现也都是类似的,比如:
public static boolean isPublic(int mod) {
return (mod & PUBLIC) != 0;
}
java中反射获取方法的修饰符
代码演示:
package com.caoguangli.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class LFrog {
public String name0;
public static String name1;
public static final String name2 = "name";
public static void main(String[] args) throws NoSuchFieldException, SecurityException {
LFrog frog = new LFrog();
Class<? extends LFrog> frogClass = frog.getClass();
Field name0 = frogClass.getField("name0");
Field name1 = frogClass.getField("name1");
Field name2 = frogClass.getField("name2");
//以整数形式返回此Field 对象所表示方法的 Java 语言修饰符
int m0 = name0.getModifiers();// 1
int m1 = name1.getModifiers();// 9(1+8)
int m2 = name2.getModifiers();// 25(1+8+16)
//0 表示没有此修饰符
System.out.println("m2 isPublic: " + (m2&1));// 1
System.out.println("m2 isPrivate: " + (m2&2));// 0
System.out.println("m2 isStatic: " + (m2&8));// 8
System.out.println("m2 isFinal: " + (m2&16));// 16
//false 表示没有被此修饰符修饰
System.out.println("m2 isPublic: " + (Modifier.isPublic(m2)));// true
System.out.println("m2 isPrivate: " + (Modifier.isPrivate(m2)));// false
System.out.println("m2 isStatic: " + (Modifier.isStatic(m2)));// true
System.out.println("m2 isFinal: " + (Modifier.isFinal(m2)));// true
}
}
运行结果:
反射怎么知道成员是被哪些修饰符所修饰的呢?
Java针对类、成员变量、方法,有很多修饰符,例如public、private、static、final、synchronized、abstract等,这些修饰符用来控制访问权限或其他特性。
本文就用成员变量(Field)来举例说明,类以及方法的修饰符获取与成员变量是一样的。
先看一个类(通过反射,可以拿到这四个变量):
package com.caoguangli.reflect;
import java.lang.reflect.Field;
public class MyTest {
public int a;
public static int b;
public static final int c = 0;
private int d;
public static void main(String[] args) {
Class<?> clazz = MyTest.class;
Field[] fields = clazz.getDeclaredFields();//获取这个类所有的成员变量
for(Field field : fields) {
System.out.println(field.getName());
}
}
}
运行结果:
现在,我想知道每个变量的带有哪些修饰符,或者是不是包含某个修饰符。
先看下Member接口:Member表示一个类中的成员,包括成员变量、方法、构造方法三种实现,上面用到的Field就是Member的一种。
Java文档:
java.lang.reflect
接口 Member
所有已知实现类:
Constructor(构造方法), Field(成员变量), Method(方法)
Member接口有个方法:
int getModifiers()
作为整数返回由此 Member所表示的成员或构造方法的 Java语言修饰符。
同时再看java.lang.Class类中也有同样的一个方法:
int getModifiers()
返回此类或接口以整数编码的 Java语言修饰符。
这个方法就是返回一个int型的返回值,代表类、成员变量、方法的修饰符。
代码演示:
package com.caoguangli.reflect;
import java.lang.reflect.Field;
public class MyTest {
public int a;
public static int b;
public static final int c = 0;
private int d;
public static void main(String[] args) {
Class<?> clazz = MyTest.class;
Field[] fields = clazz.getDeclaredFields();//获取这个类所有的成员变量
for(Field field : fields) {
System.out.print(field.getName() +"->");
System.out.println(field.getModifiers());
}
}
}
运行结果:
通过返回的int类型的值,还是很难判断这些变量有哪些修饰符。
在这里,需要用到 java.lang.reflect.Modifier 这个类。Modifier提供了很多静态方法。如public static String toString(int mod)就可以输出该整数对应的所有的修饰符。public static boolean isPublic(int mod)就可以判断该整数对应的是不是包含public修饰符。
修改上面代码,把返回的整数转换通过Modifier转换一下:
package com.caoguangli.reflect;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class MyTest {
public int a;
public static int b;
public static final int c = 0;
private int d;
public static void main(String[] args) {
Class<?> clazz = MyTest.class;
Field[] fields = clazz.getDeclaredFields();//获取这个类所有的成员变量
for(Field field : fields) {
System.out.print(field.getName() +"->");
System.out.println(Modifier.toString(field.getModifiers()));
}
}
}
运行结果:
通过Modifier的isPublic、isPrivate、isStatic等方法,可以判断是否包含某些修饰符,现在如果有这么一个需求,需要找到仅有public static两个修饰符的变量。
访问修饰符列表
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; 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值。
public static final int TRANSIENT = 0x00000080; 用transient关键字标记的成员变量不参与序列化过程。
public static final int NATIVE = 0x00000100;
public static final int INTERFACE = 0x00000200;
public static final int ABSTRACT = 0x00000400;
public static final int STRICT = 0x00000800;
即strictfp(strict float point 精确浮点),此关键字可应用于类、接口或方法。
把它们转换成二进制,可以看出,Modifier使用一个二进制的位来表示是否包含某个修饰符。
native | transient |
---|---|
public | protected |
static | final |
synchronized | – |
也就是,如果是public static,对应的整数就是二进制的:1001,也就是9。如下图:
public | 1 |
---|---|
static | 1 |
private | 1 |
final | 0 |
如果是public static final就是11001,也就是25。
现在如果想判断是否仅有public static两个修饰符,那么就可以判断是否field.getModifiers() == 9。
另外,我们也可以看到这里设计之精妙之处:用二进制位来标记是否包含某个修饰符。