Java反射类java.lang.reflect.Field类详细介绍

x33g5p2x  于2021-08-20 转载在 Java  
字(6.3k)|赞(0)|评价(0)|浏览(411)

1. 概述

一个Field可以是原始类型或引用类型。有八种原始类型:boolean, byte, short, int, long, char, float, and double。引用类型是任何直接或间接属于java.lang.Object的子类,包括接口、数组和枚举类型。

反射API提供了几种方法来分析类Field,并在运行时修改其值,在本指南中,我们将研究一些常用的方法反射函数。本帖的源代码可在GitHub上找到。
下面的类图显示了java.lang.reflect.Field类所提供的反射API的列表。

Java Reflection for Fields

2. 对Field API的反射示例

*获取所有公共Fields
*获取公共Field

  • Field 声明类
    *获取Field类型
  • 获取/设置公共Field值
  • 获取/设置私有 Field 值
    让我们首先创建User.java类,然后对它应用反射方法API。

User.java

package com.javaguides.reflection.fields;

public class User {
    public int id;
    private String name;
 
    public User(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
     this.name = name;
    }
}

2.1 获取所有公共Fields

getFields()方法返回该类的公共Fields数组,包括它的超类和超接口的公共Fields。

Class<?> concreteClass = Class.forName("com.javaguides.reflection.classes.ConcreteClass");
Field[] fields = concreteClass.getFields();
for (Field field : fields) {
    System.out.println(field.getName());
}

输出:

id

2.2 获取公共Field

Reflection API还提供了一种方法,通过getField()方法来获取一个类的特定的公共Field。这个方法在指定的类引用中寻找Field,然后在超接口中寻找,再在超类中寻找。

Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
Field field = concreteClass.getField("id");
System.out.println(field.getName());

输出:

id

2.3 Field 声明类

我们可以使用Field对象的getDeclaringClass()来获得声明Field的类。

Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
Field field = concreteClass.getField("id");
System.out.println(field.getDeclaringClass().getCanonicalName());

输出:

com.javaguides.reflection.fields.User

2.4 获取Field类型

getType()方法返回声明的Field类型的类对象,如果Field是原始类型,它返回包装类对象。

Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
Field field = concreteClass.getField("id");
System.out.println(field.getType().getCanonicalName());

输出:

int

2.5 获取/设置公共Field值

我们可以使用反射来获取和设置一个对象中的Field的值。

Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
User user = new User(10);
Field field = concreteClass.getField("id");

// Get value from concreteClass2 object
System.out.println(field.getInt(user));

// Set value to concreteClass2
field.set(user, 20);

// Get value from concreteClass2 object
System.out.println(field.getInt(user));

输出:

10
20

2.6 获取/设置私有Field值

我们知道,私有的Field和方法不能在类之外被访问,但是使用反射,我们可以通过关闭java对Field修饰符的访问检查来获取/设置私有的Field值。

Field privateField = Class.forName("com.javaguides.reflection.fields.User").getDeclaredField("name");
//turning off access check with below method call
privateField.setAccessible(true);
User user = new User(10);
System.out.println(privateField.get(user)); 
privateField.set(user, "private string updated");
System.out.println(privateField.get(user));

输出:

null
private string updated

3. 完整的源代码供参考

package com.javaguides.reflection.fields;

import java.lang.reflect.Field;

//*/*
/* Reflection For Field class API.
/* @author javaguide.net
/*
/*/
public class ReflectionForFields {
  //*/*
/* Returns a Field object that reflects the specified public member 
/* field of the class or interface represented by this Class object.
/* @throws ClassNotFoundException
/* @throws SecurityException 
/* @throws NoSuchFieldException 
/*/
 public static void pulicFields() throws ClassNotFoundException,
     NoSuchFieldException,SecurityException {
     Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
     Field field = concreteClass.getField("id");
     System.out.println(field.getName());
 }

 //*/*
/* field object to get the class declaring the field id.
/* @throws ClassNotFoundException
/* @throws NoSuchFieldException
/* @throws SecurityException
/*/
 public static void fieldDeclaringClass() throws ClassNotFoundException,
     NoSuchFieldException, SecurityException{
     Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
     Field field = concreteClass.getField("id");
     System.out.println(field.getDeclaringClass().getCanonicalName());
 }
 
 //*/*
/* getType() method returns the Class object for the declared field type, 
/* if field is primitive type, it returns the wrapper class object.
/* @throws ClassNotFoundException
/* @throws NoSuchFieldException
/* @throws SecurityException
/*/
 public static void fieldType() throws ClassNotFoundException,
     NoSuchFieldException, SecurityException{
     Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
     Field field = concreteClass.getField("id");
     System.out.println(field.getType().getCanonicalName());
 }
 
 //*/*
/* get and set public field id value.
/* @throws ClassNotFoundException
/* @throws NoSuchFieldException
/* @throws SecurityException
/* @throws IllegalAccessException 
/* @throws IllegalArgumentException 
/*/
 public static void setFieldValue() throws ClassNotFoundException, NoSuchFieldException,
     SecurityException, IllegalArgumentException, IllegalAccessException{
     Class<?> concreteClass = Class.forName("com.javaguides.reflection.fields.User");
     User user = new User(10);
     Field field = concreteClass.getField("id");
  
     // Get value from concreteClass2 object
     System.out.println(field.getInt(user));
  
     // Set value to concreteClass2
     field.set(user, 20);
  
     // Get value from concreteClass2 object
     System.out.println(field.getInt(user));
 }
 
 //*/*
/* get/set the private field value by turning off the java access check for field modifiers.
/* @throws ClassNotFoundException
/* @throws NoSuchFieldException
/* @throws SecurityException
/* @throws IllegalAccessException 
/* @throws IllegalArgumentException 
/*/
 public static void setPrivateFieldValue() throws ClassNotFoundException, 
     NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException{
     Field privateField = Class.forName("com.javaguides.reflection.fields.User").getDeclaredField("name");
     //turning off access check with below method call
     privateField.setAccessible(true);
     User user = new User(10);
     System.out.println(privateField.get(user)); // prints "private string"
     privateField.set(user, "private string updated");
     System.out.println(privateField.get(user)); //prints "private string updated"
 }
 
 public static void main(String[] args) throws ClassNotFoundException,
     NoSuchFieldException,SecurityException, IllegalArgumentException, IllegalAccessException {
     //pulicFields();
     //fieldDeclaringClass();
     //fieldType();
     //setFieldValue();
     setPrivateFieldValue();
 }
}

4. 参考资料

https://docs.oracle.com/javase/tutorial/reflect/class/index.html
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/package-summary.html
https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Field.html

相关文章