javafield类_(4)Field类的基本使⽤和解析
上⾯⼀⼩节主要讲解了class的基本⽤法和⼀些⽅法的源码解析,这⼀⼩节主要从讲解字段的基本使⽤,主要从下⾯三个⽅⾯进⾏讲解:
获取字段类型
检索和解析字段修饰符
设置和访问字段的值
字段常见错误⽤法
1.获取字段类型
下⾯的例⼦实现了⼀个类中指定字段的扫描,要得到⼀个指定字段类型,⾸先需要得到字段所在的类的类型信息,然后得到给出字段的名称的信息,然后调⽤Field("字段名称")可以得到字段的信息。
/**
* @Project: jdk
* @description: 类中字段扫描
* @author: sunkang
* @create: 2018-09-27 13:28
* @ModificationHistory who when What
**/
public class FieldSpy {
public boolean[][] b = {{ false, false }, { true, true } };
public String name = "Alice";
public List list;
public T val;
public static void args) {
/
/ args = new String[]{Name(),"b"};
args = new String[]{Name(),"val"};
try {
Class> c = Class.forName(args[0]);
Field f = c.getField(args[1]);
System.out.format("Type: %s%n", f.getType()); //getType()返回字段的类型信息
System.out.format("GenericType: %s%n", f.getGenericType());//返回字段的泛型类型信息
// production code should handle these exceptions more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
} catch (NoSuchFieldException x) {
x.printStackTrace();
}
}
}
输出结果为:
Type: class java.lang.Object
GenericType: T
思考 :
1.为什么Type 为Object类的信息呢?
原有的泛型信息会在编译期间进⾏擦除,T会被这个类型的上限进⾏取代,T的类型上限是Object,所以f.getType()为java.lang.Object的类
2.为什么GenericType()可以得到泛型的类型呢?
原因在于getgenerictype()将在类⽂件中查询签名属性,如果属性不存在则调⽤Type()⽅法,对应的源码如下:
public Type getGenericType() {
if (getGenericSignature() != null)
return getGenericInfo().getGenericType();
else
return getType();
}
private String getGenericSignature() {return signature;}
思考⼀下,那么字段的signature的字段信息是怎么设置的,泛型的信息是根据signature来进⾏解析,这⾥涉及的⽐较复杂,这个signature解析出泛型的部分暂时不看。
先看看signature怎么设置的,字段信息是从class对象来的,所以需要到Field(),对应的源
码如下:
@CallerSensitive
public Field getField(String name)
throws NoSuchFieldException, SecurityException {
checkMemberAccess(Member.PUBLIC, CallerClass(), true);
Field field = getField0(name); //到指定的字段
if (field == null) {
throw new NoSuchFieldException(name);
}
return field;
}
private Field getField0(String name) throws NoSuchFieldException {
// Note: the intent is that the search algorithm this routine
// uses be equivalent to the ordering imposed by
// privateGetPublicFields(). It fetches only the declared
// public fields for each class, however, to reduce the number
// of Field objects which have to be created for the common
// case where the field being requested is declared in the
// class which is being queried.
Field res;
// Search declared public fields 从本地声明的开始
if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res;
jdk怎么使用
}
// Direct superinterfaces, recursively //从接⼝
Class>[] interfaces = getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Class> c = interfaces[i];
if ((res = c.getField0(name)) != null) {
return res;
}
}
// Direct superclass, recursively
if (!isInterface()) {
Class> c = getSuperclass(); //从⽗类
if (c != null) {
if ((res = c.getField0(name)) != null) {
return res;
}
}
}
return null;
}
searchFields到指定的字段信息
private static Field searchFields(Field[] fields, String name) {
String internedName = name.intern();
for (int i = 0; i < fields.length; i++) {
if (fields[i].getName() == internedName) {//循环字段,然后进⾏名称匹配
return getReflectionFactory().copyField(fields[i]); //这⾥实现了字段的拷贝,关键在这个⽅法,返回的是拷贝后的对象}
}
return null;
}
最终字段的拷贝见下⾯的py()⽅法,signature签名信息是从这⾥开始设置进去的
Field copy() {
// This routine enables sharing of FieldAccessor objects
// among Field objects which refer to the same underlying
// method in the VM. (All of this contortion is only necessary
// because of the "accessibility" bit in AccessibleObject,
// which implicitly requires that new flect
// objects be fabricated for each reflective call on Class
// objects.)
if ( != null)
throw new IllegalArgumentException("Can not copy a non-root Field");
Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);//这⾥的signature被设置进来。 = this;
// Might as well eagerly propagate this if already present
res.fieldAccessor = fieldAccessor;
res.overrideFieldAccessor = overrideFieldAccessor;
return res;
}
2.检索和解析字段修饰符
先给出获取修饰符的字段的例⼦:
/**
* @Project: jdk
* @description: 字段修饰符的测试案例
* @author: sunkang
* @create: 2018-10-05 18:40
* @ModificationHistory who when What
**/
public class FieldModifierTest {
@Deprecated
private volatile int share;
enum Color { BLACK , WHITE }
public static void main(String[] args) {
try {
Class clazz = FieldModifierTest.class;
//得到指定的字段信息
Field field = DeclaredField("share");
//得到所有的修饰符之和,不同的值代表不同修饰符,但是这些值都是进⾏相加的
int modifiers = Modifiers();
/
/Modifier是⼀个⼯具类,toString 表⽰⽣成不同的修饰符
System.out.println("share字段所指定的所有的修饰符:"+String(modifiers)); //判断修饰符是否是Volatile
System.out.println("isVolatile:"+Modifier.isVolatile(modifiers));
//判断修饰符是否是私有的
System.out.println("isPrivate:"+Modifier.isPrivate(modifiers));
//得到字段的注解信息
Deprecated annotation = Annotation(Deprecated.class);
System.out.println("字段的注解信息:"+ annotation.annotationType());
//得到所有声明的字段
Field[] flds = DeclaredFields();
for (Field f: flds ){
System.out.format("%-8s [ synthetic=%-5b enum_constant=%-5b ]%n",
f.isEnumConstant());// f.isEnumConstant()表⽰是否是枚举实例
}
//EnumConstants可以得到⼀个类的枚举实例
System.out.println(Arrays.asList(EnumConstants()));
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
输出结果为:
share字段所指定的所有的修饰符:private volatile