必威体育Betway必威体育官网
当前位置:首页 > IT技术

android 用到的Java反射之Field用法

时间:2019-06-17 04:43:10来源:IT技术作者:seo实验室小编阅读:55次「手机版」
 

field

在Java反射中Field用于获取某个类的属性或该属性的属性值

一:如何通过Field反射获取类的属性

Field提供如下几种方法:

1:Class.getDeclaredField(String name);

返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段(包括私有成员)。

2:Class.getDeclaredFields();

返回 Field 对象的一个数组,该数组包含此 Class 对象所表示的类或接口所声明的所有字段(包括私有成员)。

3:Class.getField(String name);

返回一个 Field 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段。

4:Class.getFields();

返回一个包含某些 Field 对象的数组,该数组包含此 Class 对象所表示的类或接口的所有可访问公共字段。

下面一个例子说明如何通过Field反射获取类中的属性

我们先定义一个普通类Person 

包含三个属性 公有name 私有age、sex

package com.mao.test;  
  
public class Person   
{  
    public String name;  
    private Integer age;  
    private String sex;  
    //省略所有属性的set、get方法  

下面开始通过Field反射的各方法访问属性

package com.mao.test;  
  
import java.lang.reflect.Field;  
  
public class Test   
{  
    public static void main(String[]args) throws NoSuchFieldException, SecurityException  
    {  
        Person person =new Person();  
        //通过Class.getDeclaredField(String name)获取类或接口的指定已声明字段。  
        Field f1=person.getClass().getDeclaredField("name");  
        System.out.println("-----Class.getDeclaredField(String name)用法-------");  
        System.out.println(f1);  
        System.out.println("-----Class.getDeclaredFields()用法-------");  
        //通过Class.getDeclaredFields()获取类或接口的指定已声明字段。  
        Field []f2=person.getClass().getDeclaredFields();  
        for(Field field:f2)  
        {  
            System.out.println(field);  
        }  
        System.out.println("-----Class.getField(String name)用法-------");  
        //通过Class.getField(String name)返回一个类或接口的指定公共成员字段,私有成员报错。  
        Field f3=person.getClass().getField("name");  
        System.out.println(f3);  
        //如果获取age属性(私有成员) 则会报错  
        //Field f3=person.getClass().getField("name");  
        System.out.println("-----Class.getFields()用法-------");  
        //通过Class.getField(),返回 Class 对象所表示的类或接口的所有可访问公共字段。  
        Field []f4=person.getClass().getFields();  
        for(Field fields:f4)  
        {  
            //因为只有name属性为共有,因此只能遍历出name属性  
            System.out.println(fields);  
        }  
    }  
} 

通过上面程序也可以发现Class.getField(String name)和Class.getFields()都只能返回公有属性,如果访问私有属性就会报错java.lang.NoSuchFieldException。

运行结果:

-----Class.getDeclaredField(String name)用法-------  
public java.lang.String com.mao.test.Person.name  
-----Class.getDeclaredFields()用法-------  
public java.lang.String com.mao.test.Person.name  
private java.lang.Integer com.mao.test.Person.age  
private java.lang.String com.mao.test.Person.sex  
-----Class.getField(String name)用法-------  
public java.lang.String com.mao.test.Person.name  
-----Class.getFields()用法-------  
public java.lang.String com.mao.test.Person.name  

二:获取属性的属性值并修改属性值

获取属性的值用get(Object obj)的方法,但是获取私有属性的时候必须先设置Accessible为true,然后才能获取。

下面咱们获取Person各属性的属性值并将姓名属性值修改

Test.java

package com.mao.test;  
  
import java.lang.reflect.Field;  
  
public class Test   
{  
    public static void main(String[]args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException  
    {  
        Person person =new Person();  
        person.setName("VipMao");  
        person.setAge(24);  
        person.setSex("男");  
        //通过Class.getDeclaredField(String name)获取类或接口的指定属性值。  
        Field f1=person.getClass().getDeclaredField("name");  
        System.out.println("-----Class.getDeclaredField(String name)用法-------");  
        System.out.println(f1.get(person));  
        System.out.println("-----Class.getDeclaredFields()用法-------");  
        //通过Class.getDeclaredFields()获取类或接口的指定属性值。  
        Field []f2=person.getClass().getDeclaredFields();  
        for(Field field:f2)  
        {  
            field.setAccessible(true);  
            System.out.println(field.get(person));  
        }  
        //修改属性值  
        System.out.println("----修改name属性------");  
        f1.set(person, "Maoge");  
        //修改后再遍历各属性的值  
        Field []f3=person.getClass().getDeclaredFields();  
        for(Field fields:f3)  
        {  
            fields.setAccessible(true);  
            System.out.println(fields.get(person));  
        }  
          
    }  
}  

从上面程序我们得知,通过get(Object obj)获取属性的值,通过set(Object obj,value)重新设置新的属性值,并且当我们需要获取私有属性的属性值得时候,我们必须设置Accessible为true,然后才能获取。

运行结果:

-----Class.getDeclaredField(String name)用法-------  
VipMao  
-----遍历属性值-------  
VipMao  
24  
男  
----修改name属性后再遍历属性值------  
Maoge  
24  
男 

转:https://blog.csdn.net/VipMao/article/details/51638547

另外附上

Field定义:

//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  
            }  
        }  
    }  
  
}

相关阅读

c语言strcpy()用法

c语言strcpy()用法 strcpy,即string copy(字符串复制)的缩写。strcpy是一种C语言的标准库函数,strcpy把从src地址开始且含有’\0’结

2018年支持java8的Java反编译工具汇总

大多商业软件,会对程序进行加密、加壳等安全措施以防范软件被破解,从而使得反编译越来越难。反编译是一个对目标可执行程序进行逆向

共有18款Java 代码混淆和加密开源软件

http://www.oschina.net/project/tag/167/code-confusion?lang=19&sort=view Java混淆器 ProGuard ProGuard 是一个免

在java类中定义常量的三中方法

主要讲解如何在java类中定义常量:/** * Method One */ interface ConstantInterface { String SUNDAY = "SUNDAY"; Stri

关于Toast.makeText()用法的简单说明

正如这段代码:Toast.makeText(this, "You clicked Add", Toast.LENGTH_SHORT).show();Toast的用法很简单,通过静态方法makeText()创

分享到:

栏目导航

推荐阅读

热门阅读