文档章节

聊一聊Java反射中的Field

trayvon
 trayvon
发布于 2017/04/08 22:01
字数 1328
阅读 42
收藏 0
点赞 0
评论 0

简介

Java中一个重要的机制就是反射了,很多自动化的功能都是通过反射完成的,这对很多框架是非常重要的,因为很多框架就是做顶层抽象处理公用的逻辑,所以对于实现层的东西是不清楚的,有了反射机制,框架就可以在运行时获取到自己需要的实现层的一些信息,从而做更多的事情。

Java的的反射包java.lang.reflect中提供的最常用且重要的几个类就是Field、Method、Constructor这3个类了,这3个类提供的接口很类似,所以这里就先聊一聊Field这个类

实例

这里我们通过一个实例来说一下Field类中常用的接口的意义用法和一下注意事项。field代表的是字段,所以我们先来一个实体bean

public class FieldBean <T>{
    
    @FieldAnnotation(type="int",filedName="intField")
    @FieldId
    private int intField;
    
    @FieldAnnotation(type="String",filedName="stringField")
    private String stringField;
    
    @FieldAnnotation(type="char",filedName="charField")
    private char charField;
    
    @FieldAnnotation(type="double",filedName="doubleField")
    private double doubleField;
    
    @FieldAnnotation(type="long",filedName="longField")
    private long longField;
    
    @FieldAnnotation(type="short",filedName="shortField")
    private short shortField;
    
    @FieldAnnotation(type="byte",filedName="byteField")
    private byte byteField;
    
    @FieldAnnotation(type="float",filedName="floatField")
    private float floatField;
    
    public int publicField;
    
    public static int publicStaticField;
    
    public final static int publicFinalStaticField = 0;
    
    private T objectField;

    public int getIntField() {
        return intField;
    }

    public void setIntField(int intField) {
        this.intField = intField;
    }

    public String getStringField() {
        return stringField;
    }

    public void setStringField(String stringField) {
        this.stringField = stringField;
    }

    public char getCharField() {
        return charField;
    }

    public void setCharField(char charField) {
        this.charField = charField;
    }

    public double getDoubleField() {
        return doubleField;
    }

    public void setDoubleField(double doubleField) {
        this.doubleField = doubleField;
    }

    public long getLongField() {
        return longField;
    }

    public void setLongField(long longField) {
        this.longField = longField;
    }

    public short getShortField() {
        return shortField;
    }

    public void setShortField(short shortField) {
        this.shortField = shortField;
    }

    public byte getByteField() {
        return byteField;
    }

    public void setByteField(byte byteField) {
        this.byteField = byteField;
    }

    public float getFloatField() {
        return floatField;
    }

    public void setFloatField(float floatField) {
        this.floatField = floatField;
    }

    public int getPublicField() {
        return publicField;
    }

    public void setPublicField(int publicField) {
        this.publicField = publicField;
    }

    public static int getPublicStaticField() {
        return publicStaticField;
    }

    public static void setPublicStaticField(int publicStaticField) {
        FieldBean.publicStaticField = publicStaticField;
    }

    public T getObjectField() {
        return objectField;
    }

    public void setObjectField(T objectField) {
        this.objectField = objectField;
    }

    public static int getPublicfinalstaticfield() {
        return publicFinalStaticField;
    }

    @Override
    public String toString() {
        return "FieldBean [intField=" + intField + ", stringField=" + stringField + ", charField=" + charField
                + ", doubleField=" + doubleField + ", longField=" + longField + ", shortField=" + shortField
                + ", byteField=" + byteField + ", floatField=" + floatField + ", publicField=" + publicField
                + ", objectField=" + objectField + "]";
    }
    
    public static <E> FieldBean<E> getDefaultFieldBean(E object){
        FieldBean<E> bean = new FieldBean<E>();
        bean.byteField = Byte.MAX_VALUE;
        bean.charField = 'c';
        bean.doubleField = Double.MIN_NORMAL;
        bean.floatField = Float.MAX_VALUE;
        bean.intField = Integer.MAX_VALUE;
        bean.longField = Long.MAX_VALUE;
        bean.shortField = Short.MAX_VALUE;
        bean.stringField = "string";
        bean.objectField = object;
        return bean;
    }

}

上面的实体bean使用到的2个注解:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldAnnotation {
    
    public String type();
    
    public String filedName();

}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface FieldId {

}

主类:

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Date;

public class FieldStart {
    
    public static void main(String[] args) {
        Date date = new Date(System.currentTimeMillis());
        FieldBean<Date> bean = FieldBean.getDefaultFieldBean(date);
        System.out.println(bean);
        Class<?> clazz = bean.getClass();
        Field[] fields = clazz.getDeclaredFields();
        printFieldInfo(fields);
        dealIntField(clazz,bean);
        dealGetGenericType(clazz);
    }
    
    private static void dealGetGenericType(Class<?> clazz){
        try {
            Field field = clazz.getDeclaredField("objectField");
            Type type = field.getGenericType();
            System.out.println(type);
            System.out.println(type instanceof TypeVariable);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
    }
    
    private static void dealIntField(Class<?> clazz,FieldBean<Date> bean){
        try {
            Field intField = clazz.getDeclaredField("intField");
            Annotation[] annotations = intField.getAnnotations();
            for (int i = 0; i < annotations.length; i++) {
                System.out.println(annotations[i]);
            }
            FieldAnnotation fieldAnnotation = intField.getAnnotation(FieldAnnotation.class);
            System.out.println(fieldAnnotation.type()+"  "+fieldAnnotation.filedName());
            intField.setAccessible(true);
            int intValue = intField.getInt(bean);
            System.out.println(intValue);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }
    
    private static void printFieldInfo(Field[] fields){
        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            System.out.println("name:"+field.getName());
            System.out.println("modify:"+Modifier.toString(field.getModifiers()));
            System.out.println("declaringClass:"+field.getDeclaringClass());
            System.out.println("genericType:"+field.getGenericType());
            System.out.println("type:"+field.getType());
        }
    }

}

下面以FieldBean中的intField为例来介绍一下各个接口:

@FieldAnnotation(type="int",filedName="intField")
@FieldId
private int intField;

使用最多的接口getName()接口,这个接口就是获取字段的名字,那么上面这个字段代表的Field实例上调用getName()接口,获取的值就是intField。

另外2个常用的接口就是getAnnotations()和getAnnotation(Class)了,getAnnotations()是获取字段上的所有注解实例,同样如上面的字段代表的Field调用getAnnotations()获取到的就是包含了FieldAnnotation和FieldId的数组。调用getAnnotation(FieldAnnotation.class)获取的就是FieldAnnotation的实例,调用getAnnotation(FieldId.class)就是获取的FieldId实例。

注解的确是非常方便的,所以很多框架就通过注解来避免xml配置和强制继承,进而避免和实现层的强耦合,也避免了侵入到实现层的代码中。例如:在类上的注解@Controller,在参数上的注解@Param,在字段上的注解@JSONField,@Id,@Resource,@Autowired等。

获取值,Field类提供了getInt(Object),getLong(Object)等基本类型的方法来获取object实例对应的值,也提供了getObject(Object)接口。 注意:获取值的接口是有访问权限的可以通过setAccessible(true);来避免权限检查。

getDeclaringClass()接口是获取字段所在的类Class,上面的intField字段所代表的Filed实例上调用getDeclaringClass()获取的就是FieldBean.class

getType()接口是获取字段的类型,上面的intField字段所代表的Filed实例上调用getType()获取到的值就是int.class

getModifiers()接口是获取字段的修饰符,例如下面的intField字段所代表的Filed实例上调用getModifiers()方法获取的就是public static final,注意:getModifiers()获取到的是一个int类型的可以通过Modifier.toString(field.getModifiers()))转换一下。

public final static int publicFinalStaticField = 0;

getGenericType()接口是获取字段的泛型类型,例如下面的intField字段所代表的Filed实例上调用getGenericType()获取到的就是:T,实际的类型是TypeVariable

private T objectField;

总结

  1. Field可以通过getName获取字段名称
  2. Field可以通过getAnnotations()和getAnnotation(Class)获取字段注解
  3. Field可以通过getInt(Object)获取指定对象字段的值
  4. 通过setAccessible(true)可以访问私有字段

© 著作权归作者所有

共有 人打赏支持
trayvon
粉丝 14
博文 120
码字总数 178809
作品 1
程序员
新浪、百度、好未来3offer到手全记录 | 牛客面经

新浪、百度、好未来3offer到手全记录 牛客面经 原创 2017-09-19 牛友 招聘消息汇总 渣渣的秋招之路 附上新浪,百度,好未来面经 作者:offer快到碗里来?。! 来源:牛客网 楼主是本科渣渣,...

公子只识黛玉
04/17
0
0
Direct Memory只会在Full GC时回收

今天面试一个senior的老同事 聊的GC很细节当聊到jvm优化时 老兄提到了 给jvm加参数取消 System.gc() 来避免gc的频繁调动因为在netty中显式调用的地方所以有点疑惑人走后特意查了下 soga Dir...

xffforever
2014/04/02
0
0
sharding-jdbc源码解析全集

本文转自“天河聊技术”微信公众号 sharding-jdbc源码解析之词法解析 sharding源码解析之api分析 sharding-jdbc源码解析之spring集成 sharding-jdbc源码解析之spring集成分片构造实现 shardi...

天河2018
05/03
0
0
java 过滤list的几种方式

java中 过滤list的几种方式 方式一:使用java 8语法:stream+反射 抽取为通用的过滤方法: 进一步抽取: 方式二:遍历+反射 反射类 ReflectHWUtils 见 https://github.com/liuyu520/io0007 的com...

黄威
07/02
0
0
类名.class, class.forName(), getClass()区别

1:Class cl=A.class; JVM将使用类A的类装载器, 将类A装入内存(前提是:类A还没有装入内存),不对类A做类的初始化工作.返回类A的Class的对象。 2:Class cl=对象引用o.getClass(); 返回引用o运行...

LCZ777
2014/09/17
0
0
Java中的String对象是不可变的吗

有个仁兄在 StackOverflow 上发起了一个问题,是这么问的: 众所周知Java中的String对象是不可变的,但我们来看下面这段代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 String s1 ...

LCZ777
2014/03/25
0
0
java反射机制在项目中的运用

定义: Reflection是java开发语言特性之一,它允许运行中的java程序对自身进行检测,自审,并能操作程序内部的属性和方法,Reflection是java被视为动态语言关键之一。允许程序从执行期的Ref...

zhoulc
2014/02/24
0
2
Git撤销已经推送(push)至远端仓库的提交(commit)信息

有时,在git push之后,才发现还有一些代码需要进行很小的改动,这些改动在原则上不应该作为一次新的提交。这时,我们需要撤销这次推送(git push)与提交(git commit),然后进行代码修改,再重...

春哥大魔王的博客
07/05
0
0
RTTI VS Reflection

1.RTTI( Run-Time Type Information) RTTI( Run-Time Type Information)的主要作用就是运行期鉴定对象的类型,比如需要塑形的时候,使用instanceof判断类型的时候。Java用Class对象实现自...

enosh
2014/12/25
0
0
聊聊我面试过的一个最奇葩的 Java 程序猿!

上周我聊了聊最让我反感的 10 种程序猿,无奈一个小时就进行了删除,详细原因就不说了,容易招黑。 今天聊的我面试过的最奇葩的一个程序猿,绝对是奇葩中的奇葩,简直是程序猿中的另类,最让...

Java技术栈
06/10
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Python PIPEs

https://www.python-course.eu/pipes.php https://www.tutorialspoint.com/python/os_pipe.htm

zungyiu
2分钟前
0
0
gRPC学习笔记

gRPC编程流程 1. proto文件定义 proto文件用于定义需要通过gRPC生成的接口,可以理解为接口定义文档 2. 通过构建工具生成服务基类代码-Maven或Gradle 3. 服务端开发 服务端实现类须实现通过构...

OSC_fly
22分钟前
0
0
Docker Mac (三) Dockerfile 及命令

Dockerfile 最近学习docker的时候,遇到一件怪事,关于docker镜像可能会被破坏,还不知道它会有此措施 所以需要了解构建Dockerfile的正确方法 Dockerfile是由一系列命令和参数构成的脚本,这些命...

___大侠
49分钟前
0
0
Android Studio+NDK+Cmake 移植FFmpeg-4.0.2命令行工具

一、编译 参考大神的帖子,亲测一次编译成功:https://blog.csdn.net/bobcat_kay/article/details/80889398 鉴于以前查文档的经验,这里附上编写例子的时间:2018年7月22日 我用的是ubantu,...

她叫我小渝
49分钟前
0
0
mysql创建数据库

登录MYSQL mysql -u root -p 脚本创建数据库WeChat,并制定默认的字符集是utf8mb4。 CREATE DATABASE Wechat DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 授权 grant all......

niithub
今天
0
0
svn: Unable to connect to a repository URL 的解决方案

错误图示: 解决办法:清除本地保存的授权信息; 1:右键点击本地文件夹,选择设置; TortoiseSVN -> Settings 2:在弹出的对话框中选择 Saved Data, 右侧选择:授权地方清理所有。 然后点确...

宁哥实战课堂
今天
1
0
sleep与wait的区别

Thread.sleep(XXX)方法消耗CPU吗? 这个知识点是我之前认识一直有错误的一个知识点,在我以前的认识里面,我一直认为Thread.sleep(1000)的这一秒钟的时间内,线程的休眠是一直占用着CPU的时间...

码代码的小司机
今天
1
0
20位活跃在Github上的国内技术大牛 leij 何小鹏 亚信

本文列举了20位在Github上非常活跃的国内大牛,看看其中是不是很多熟悉的面孔? 1. lifesinger(玉伯) Github主页: https://github.com/lifesinger 微博:@ 玉伯也叫射雕 玉伯(王保平),...

海博1600
今天
1
0
Mybatis收集配置

一、Mybatis取Clob数据 1、Mapper.xml配置 <resultMap type="com.test.User" id="user"> <result column="id" property="id"/> <result column="json_data" property="jsonData" ......

星痕2018
今天
1
0
centos7设置以多用户模式启动

1、旧版本linux系统修改inittab文件,在新版本执行vi /etc/inittab 会有以下提示 # inittab is no longer used when using systemd. # # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON......

haha360
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部