5.1 JDK源码阅读之Field

 

成员变量

 

 

每个成员变量有类型

java.lang.reflect.Field 为我们提供了获取当前对象的成员变量的类型,和重新设值的方法。

获取变量的类型

类中的变量分为两种类型:基本类型引用类型

  • 基本类型( 8 种) 
    • 整数:byte, short, int, long
    • 浮点数:float, double
    • 字符:char
    • 布尔值:boolean
  • 引用类型 
    • 所有的引用类型都继承自 java.lang.Object
    • 类,枚举,数组,接口都是引用类型
    • java.io.Serializable 接口,基本类型的包装类(比如 java.lang.Double)也是引用类型
  • 主要方法

    getType(): 获取属性声明时类型对象(返回class对象)

    getGenericType() : 返回属性声的Type类型

    getName() : 获取属性声明时名字

    getAnnotations() : 获得这个属性上所有的注释

    getModifiers() : 获取属性的修饰

    isEnumConstant() : 判断这个属性是否是枚举类

    isSynthetic() : 判断这个属性是否是 复合类

    get(Object obj) : 取得obj对象这个Field上的值

    set(Object obj, Object value) : 向obj对象的这个Field设置新值value

    Field类中最常用的是get(Object obj)和set(Object obj, Object value)这两个方法,所以这两个方法是最重要的。

    getType() 和 getGenericType()的区别 :

    1.首先是返回的类型不一样,一个是Class对象一个是Type接口

    2.如果属性是一个泛型,从getType()只能得到这个属性的接口类型。但从getGenericType()还能得到这个泛型的参数类型。

    isEnumConstant()和isSynthetic() :

    对象中如果有属性是枚举类或复合类,用这两个方法返回的值并不是我们想象的true而是false。其实这两个方法是对编译生成的才有效。

  • //AccessibleObject 类是 Field、Method 和 Constructor 对象的基类。
    public class AccessibleObject implements AnnotatedElement {
    	/*
    	 * 1、实现了AnnotatedElement对注解支持的相关方法
    	 * 2、提供访问控制 
    	 /
    	void setAccessible(boolean flag) 
    	设置该对象(Field,Constructor,Method)是否可访问
    	boolean isAccessible() 
    	该对象是否可访问
    	void setAccessible(AccessibleObject[] array, boolean flag) 
    	设置这一组对象(Field,Constructor,Method)是否可访问
    }
    public interface Member{
       public static final int PUBLIC = 0; //标识类或接口的所有已声明成员的集合。
       public static final int DECLARED = 1; //标识类或接口的所有公共成员(包括继承成员)的集合。
       
       public Class<?> getDeclaringClass();// 所在类
       public String getName(); //返回此 Member 表示的底层成员或构造方法的简单名称。
       public int getModifiers(); //作为整数返回由此 Member 所表示的成员或构造方法的 Java 语言修饰符。
       public boolean isSynthetic(); //如果此成员是编译器引入的,则返回 true;否则,返回 false。
    }
    public final class Field extends AccessibleObject implements Member{
     
       // 1.字段的设值和取值 ,对于静态属性,obj传null
    	set(Object obj, Object value) 
    	setXX(Object obj, Object value) ,比如setInt,setBoolean
    	Object get(Object obj)
    	getXX(Object obj) ,比如getInt,getBoolean
    	
    	
    	// 2.字段上注解的获取
    	getDeclaredAnnotations() 
    	getAnnotation(Class<T> annotationClass); 
    	
    	// 3.字段类型
    	  Type getGenericType();
    	  Class<?> getType();
    	// 4.字段修饰符
    	  int modifer=field.getModifiers();
    	  String modify = Modifier.toString(modifiers);
    	// 5.字段名称
    	 String getName();
    }
    

     

 Field类实例

package reflect;
 
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Arrays;
import java.util.List;
 
/**
 * @author zhangquanit
 */
public class FieldTest {
 
	private int mInt; // 普通成员变量
 
	public static String mStr; // 静态成员变量
 
	@MyAnnotation
	private Object mObject; // 使用了注解的成员变量
 
	private List<String> mList; // 泛型字段
 
	public static void main(String[] args) throws Exception {
		FieldTest obj = new FieldTest();
		Class<? extends FieldTest> clazz = obj.getClass();
 
		/*
		 * 普通属性字段的设置和获取
		 */
		Field normalField = clazz.getDeclaredField("mInt");
		setAccessible(normalField);
		String filedName=normalField.getName();//mInt
		normalField.set(obj, 100); // 设值
		int mIntValue = normalField.getInt(obj);// 取值 100;
 
		/*
		 * 静态属性字段的设值和获取 (obj传null)
		 */
		Field staticField = clazz.getDeclaredField("mStr");
		setAccessible(staticField);
		staticField.set(null, "static value");
		Object value = staticField.get(null);// static value
 
		/*
		 * 字段的枚举相关操作 (更多相关信息参照 我写的 Java注解)
		 */
		Field annotationField = clazz.getDeclaredField("mObject");
		setAccessible(annotationField);
		Annotation[] declaredAnnotations = annotationField
				.getDeclaredAnnotations();
		System.out.println(Arrays.toString(declaredAnnotations));
 
		/*
		 * 泛型字段
		 */
		Field genericField = clazz.getDeclaredField("mList");
		setAccessible(genericField);
		Type genericType = genericField.getGenericType();// java.util.List<java.lang.String>
		Class type = genericField.getType(); // interface java.util.List
		getActualType(genericType); //Class类型: class java.lang.String
 
	}
 
	// 私有的变量,需要设置为可访问
	private static void setAccessible(Field field) {
		if (!field.isAccessible()) {
			field.setAccessible(true);
		}
	}
 
	// 获取List中泛型的实际类型
	private static void getActualType(Type genericType) {
		if (genericType instanceof ParameterizedType) {
			ParameterizedType parameterizedType = (ParameterizedType) genericType;
			Type actualType = parameterizedType.getActualTypeArguments()[0];
			if (actualType instanceof TypeVariable) {// 泛型类型,比如T
				TypeVariable typeVariable = (TypeVariable) actualType;
				System.out.println("TypeVariable类型: " + typeVariable);
 
			} else if (actualType instanceof WildcardType) {// 含通配符? 类型
				WildcardType wildcardType = (WildcardType) actualType;
				System.out.println("WildcardType类型: " + wildcardType);
 
			} else if (actualType instanceof Class) { // 普通类对象
				Class cls = (Class) actualType;
				System.out.println("Class类型: " + actualType); // class
																// java.lang.String
			}
		}
	}
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值