JDK源码/*分析 :反射包 java.lang.reflect③ 之 Field 获取类的属性字段信息

时间:2021-03-07 15:23:57

    今天的主角:java.lang.reflect.Field

    继前面说的,一个类有它的抽象,构造方法有它的抽象,当然我们类中的字段也可以有它的抽象。
Field 也就是我们说的字段,类中的属性。一般地我们在类中看到的样子是这样的:
private String privateStr ;
public static final  String publicStr ;
         String protectStr ;
public static final String finalStr = "110" ;
    从上面可以看出,一个字段对象应该有5部份:字段的权限(private、public、protect),是否静态是否不可变,字段的类型(String、Date等),字段名,字段值。

获取Field 对象

    Class 对象中获取Field 对象的方法有:
     获取所有权限的字段
    Field    getDeclaredField(String name)
    Field[]    getDeclaredFields()

获取公共权限的字段
    Field    getField(String name)
    Field[]    getFields()

    首先贴上我们的测试pojo类
package com.hlmtest.java.reflect;
public class TestFieldClass {
      private String privateStr ;
      public   String publicStr ;
                String protectStr ;
      public static final String finalStr = "110" ;
     
      public TestFieldClass(){}
     
      public TestFieldClass(String privateStr ,String publicStr ,String protectStr ){
            this . privateStr = privateStr ;
            this . publicStr = publicStr ;
            this . protectStr = protectStr ;
           
     }
      public String getPrivateStr() {
            return privateStr ;
     }
      public void setPrivateStr(String privateStr ) {
            this . privateStr = privateStr ;
     }
      public String getPublicStr() {
            return publicStr ;
     }
      public void setPublicStr(String publicStr ) {
            this . publicStr = publicStr ;
     }
      public String getProtectStr() {
            return protectStr ;
     }
      public void setProtectStr(String protectStr ) {
            this . protectStr = protectStr ;
     }
      public String toString(){
            return "privateStr:" + privateStr + ";publicStr:" + publicStr + ";protectStr:" + protectStr + ";finalStr:" + finalStr ;          
     }
           
}

package com.hlmtest.java.reflect;
import java.lang.reflect.Field;
public class TestFieldObject {
      public static void main(String[] args ) {
            getFieldInfo ();
     }
     
      public static void getFieldInfo(){
            //先获取Class 对象实例
           Class<TestFieldClass> clzz = TestFieldClass. class ;
           Field[] DeclFieldList clzz .getDeclaredFields();
            for (Field field : DeclFieldList ){
                System. out .println( field .toString()+ ";" );
           }
           System. out .println( "<--我是华丽的分割线-->" );
           
           Field[] PublFieldList clzz .getFields();
            for (Field field : PublFieldList ){
                System. out .println( field .toString()+ ";" );
           }
           
     }
}
    运行结果为:
private java.lang.String com.hlmtest.java.reflect.TestFieldClass.privateStr;
public java.lang.String com.hlmtest.java.reflect.TestFieldClass.publicStr;
java.lang.String com.hlmtest.java.reflect.TestFieldClass.protectStr;
public static final java.lang.String com.hlmtest.java.reflect.TestFieldClass.finalStr;
<--我是华丽的分割线-->
public java.lang.String com.hlmtest.java.reflect.TestFieldClass.publicStr;
public static final java.lang.String com.hlmtest.java.reflect.TestFieldClass.finalStr;

取字段值

    根据字段名取得字段
package com.hlmtest.java.reflect;
import java.lang.reflect.Field;
public class TestFieldObject {
      public static void main(String[] args ) throws NoSuchFieldException, SecurityException {
            getFieldInfo ();
     }
     
      public static void getFieldInfo() throws NoSuchFieldException, SecurityException{
            //先获取Class 对象实例
           Class<TestFieldClass> clzz = TestFieldClass. class ;
           Field field clzz .getDeclaredField( "publicStr" );
           System. out .println( field .toString()+ ";" );
           
     }
     
}     

运行结果:
public java.lang.String com.hlmtest.java.reflect.TestFieldClass.publicStr;

通过Field 对象获取某实例的字段值: Object    get(Object obj)
import java.lang.reflect.InvocationTargetException;
public class TestFieldObject {
      public static void main(String[] args ) throws NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            getFieldInfo ();
     }
     
      public static void getFieldInfo() throws NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            //先获取Class 对象实例
           Class<TestFieldClass> clzz = TestFieldClass. class ;
           
            //获取有参的构造方法对象
            @SuppressWarnings ( "rawtypes" )
           Class[] paramstr = {String. class ,String. class ,String. class };
           Constructor<TestFieldClass> instance = clzz .getConstructor( paramstr );
            //调用Constructor 的newInstance(Object... initargs ) 方法获得主对象实例
           TestFieldClass obj = instance .newInstance( "我是私有属性" , "我是公共属性" , "我是默认属性" );
           
           Field field clzz .getDeclaredField( "publicStr" );
           Object valueObj = field .get( obj );
           System. out .println( valueObj .toString()+ "" );
           
           Field[] fieldList clzz .getFields();
            for (Field f : fieldList ){
                Object value = f .get( obj );
                System. out .println( f .toString()+ "-->" + value .toString()+ ";" );
           }
     }
}
运行结果
我是公共属性
public java.lang.String com.hlmtest.java.reflect.TestFieldClass.publicStr-->我是公共属性;
public static final java.lang.String com.hlmtest.java.reflect.TestFieldClass.finalStr-->110;
要注意的是,这个方法只能获取公共字段的值,私有字段的值是无法获取 的,硬来要获取则会报:java.lang.IllegalAccessException
并且会告诉你 你这个Class  can not access a member of 某类 with modifiers "private"。道理很简单,私有的属性本来就是供人家自己用的,你不可能在外面直接操作人家的。

设置字段值

可以获取字段值自然就可以设置字段值,方法是:void    set(Object obj, Object value)
package com.hlmtest.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class TestFieldObject {
      public static void main(String[] args ) throws NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            getFieldInfo ();
     }
     
      public static void getFieldInfo() throws NoSuchFieldException, SecurityException, NoSuchMethodException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            //先获取Class 对象实例
           Class<TestFieldClass> clzz = TestFieldClass. class ;
           
            //获取有参的构造方法对象
            @SuppressWarnings ( "rawtypes" )
           Class[] paramstr = {String. class ,String. class ,String. class };
           Constructor<TestFieldClass> instance = clzz .getConstructor( paramstr );
            //调用Constructor 的newInstance(Object... initargs ) 方法获得主对象实例
           TestFieldClass obj = instance .newInstance( "我是私有属性" , "我是公共属性" , "我是默认属性" );
           
            //与取值一样,私有的字段也是不可以直接设值的,所以此处只取公共字段    
           Field[] fieldList clzz .getFields();
            for (Field f : fieldList ){
                 //final 修饰的字段是不可设值的,否则会报错,这里得排除
                 if ( f .toString().indexOf( "final" )>-1){
                      continue ;
                }
                 f .set( obj , f .getName()+ "我给你设值了哈" );
                Object value = f .get( obj );
                System. out .println( f .toString()+ "-->" + value .toString()+ ";" );
           }
     }
}
    运行结果:
public java.lang.String com.hlmtest.java.reflect.TestFieldClass.publicStr-->publicStr我给你设值了哈;

    到此也就差不多了,大家想要了解更多的使用方法的话当然还是文档啦。

Field 的更多API可以查询:

其他

其他反射相关博客:

    JDK源码/*分析 :反射包 java.lang.reflect② 之 Constructor 获取类的实例对象;

    JDK源码/*分析 :反射包 java.lang.reflect ①之 Class 探秘;



    201800602