Java8通过Function获取字段名的方法(获取实体类的字段名称)
作者:一抹微笑~ 发布时间:2021-05-23 12:24:19
标签:Java8,Function,字段名
看似很鸡肋其实在某些特殊场景还是比较有用的。
比如你将实体类转Map或者拿到一个Map结果的时候,你是怎么获取某个map的key和value。
方法一:
声明 String key1="aaa"; key为 key1,value 为map.get(key1);
Map<String,Object> map=new HashMap<>();
map.put("aaa",1);
//获取map的key 和value
//key 为key1
String key1="aaa";
//value 为 map.get(key1)
map.get(key1);
然后好像日常使用中也没有其他的方法了,下面将带来另外一种使用方法,话不多说直接上代码[/code]
import java.io.Serializable;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Function;
/**
* Java8通过Function函数获取字段名称(获取实体类的字段名称)
* @see ColumnUtil#main(java.lang.String[]) 使用示例
* @author jx
*/
public class ColumnUtil {
/**
* 使Function获取序列化能力
*/
@FunctionalInterface
public interface SFunction<T, R> extends Function<T, R>, Serializable {
}
/**
* 字段名注解,声明表字段
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableField {
String value() default "";
}
//默认配置
static String defaultSplit = "";
static Integer defaultToType = 0;
/**
* 获取实体类的字段名称(实体声明的字段名称)
*/
public static <T> String getFieldName(SFunction<T, ?> fn) {
return getFieldName(fn, defaultSplit);
}
/**
* 获取实体类的字段名称
* @param split 分隔符,多个字母自定义分隔符
*/
public static <T> String getFieldName(SFunction<T, ?> fn, String split) {
return getFieldName(fn, split, defaultToType);
}
/**
* 获取实体类的字段名称
* @param split 分隔符,多个字母自定义分隔符
* @param toType 转换方式,多个字母以大小写方式返回 0.不做转换 1.大写 2.小写
*/
public static <T> String getFieldName(SFunction<T, ?> fn, String split, Integer toType) {
SerializedLambda serializedLambda = getSerializedLambda(fn);
// 从lambda信息取出method、field、class等
String fieldName = serializedLambda.getImplMethodName().substring("get".length());
fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase());
Field field;
try {
field = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName);
} catch (ClassNotFoundException | NoSuchFieldException e) {
throw new RuntimeException(e);
}
// 从field取出字段名,可以根据实际情况调整
TableField tableField = field.getAnnotation(TableField.class);
if (tableField != null && tableField.value().length() > 0) {
return tableField.value();
} else {
//0.不做转换 1.大写 2.小写
switch (toType) {
case 1:
return fieldName.replaceAll("[A-Z]", split + "$0").toUpperCase();
case 2:
return fieldName.replaceAll("[A-Z]", split + "$0").toLowerCase();
default:
return fieldName.replaceAll("[A-Z]", split + "$0");
}
}
}
private static <T> SerializedLambda getSerializedLambda(SFunction<T, ?> fn) {
// 从function取出序列化方法
Method writeReplaceMethod;
try {
writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
// 从序列化方法取出序列化的lambda信息
boolean isAccessible = writeReplaceMethod.isAccessible();
writeReplaceMethod.setAccessible(true);
SerializedLambda serializedLambda;
try {
serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
writeReplaceMethod.setAccessible(isAccessible);
return serializedLambda;
}
/**
* 测试用户实体类
*/
public static class TestUserDemo implements Serializable {
private static final long serialVersionUID = 1L;
private String loginName;
private String name;
private String companySimpleName;
@ColumnUtil.TableField("nick")
private String nickName;
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public static long getSerialVersionUID() {
return serialVersionUID;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCompanySimpleName() {
return companySimpleName;
}
public void setCompanySimpleName(String companySimpleName) {
this.companySimpleName = companySimpleName;
}
}
/**
* 参考示例
*/
public static void main(String[] args) {
//实体类原字段名称返回
System.out.println();
System.out.println("实体类原字段名称返回");
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getLoginName));
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getNickName));
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName));
System.out.println();
System.out.println("实体类字段名称增加分隔符");
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_"));
System.out.println();
System.out.println("实体类字段名称增加分隔符 + 大小写");
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 0));
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 1));
System.out.println("字段名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 2));
}
}
输出结果:
来源:https://www.cnblogs.com/IT-study/p/15351980.html


猜你喜欢
- 前言.如何设置设置使用的地方1.设置类注释模板代码/*** @author: lujie* @create: $date$* @descri
- 一、本文来由由于网络不稳定的原因,所以想着启动本地nacos来运行项目,但是nacos启动没问题了,但是依旧报错。Caused by: co
- 下面是我自己收集整理的2017年Java岗位的面试题,可以用它来好好准备面试。一、Java基础1. String类为什么是final的。2.
- 本文实例为大家分享了Android实现简单计时器的具体代码,供大家参考,具体内容如下布局在res/layout 下进行布局<?xml
- 简介Spring Security,这是一种基于 Spring AOP 和 Servlet 过滤器的安全框架。它提供全面的安全性解决方案,同
- 序言在flutter开发中,我们使用 bloc 框架,基于状态变更进行响应式开发。本篇文章,小轰将 bloc 核心业务块进行拆解简化,聊一聊
- Java中有两类线程:User Thread(用户线程)、Daemon Thread(守护线程)用户线程即运行在前台的线程,而守护线程是运行
- 经过各种各样的整理,以及和热心网友讨论,终于整理出了九种android开发中最常见的问题和解决方案再次跟大家分享下!!有用的话请顶顶帖子,共
- 本文以Java程序代码为例展示如何通过格式转换的方式将PPT幻灯片文档转为HTML文件。这里的PPT幻灯片可以是.ppt/.pptx/.pp
- 本文实例讲述了Hibernate批量处理海量数据的方法。分享给大家供大家参考,具体如下:Hibernate批量处理海量其实从性能上考虑,它是
- 本文实例讲述了C#编程实现自定义热键的方法。分享给大家供大家参考。具体实现方法如下:using System;using System.Co
- 如下所示:package cn.jdk.foreach;import java.util.HashMap;import java.util.
- 1、悬浮窗的基本介绍悬浮窗,大家应该也不陌生,凌驾于应用之上的一个小弹窗,实现上很简单,就是添加一个系统级别的窗口,Android中通过Wi
- 个人理解:把一个类里的多个命令分离出来,每个类里放一个命令,实现解耦合,一个类只对应一个功能,在使用命令时由另一个类来统一管理所有命令。缺点
- 该系统分为前台和后台,前台可以自主注册,后台管理员角色,除基础脚手架外,实现的功能有:后台管理员功能有:商品分类管理、商品管理、套餐管理、新
- 1、比较器①比较器的引入a.首先,当我们单一地比较某一种数据类型的数组时,可以直接用Arrays.sort()进行实现b.而当我们同时含有多
- 下面的每一步应该都必不可少:1、启动类继承这个类,并且重新configure这个方法,return builder.sources(Code
- 1、java中启动exe程序 ,并添加传参String[] cmd = {"hh.exe","12315&qu
- 本文实例讲述了Android实时文件夹创建方法。分享给大家供大家参考。具体如下:实时文件夹是一种用来显示由某个ContentProvider
- 如题,记录一些平常开发用的pom文件细节1.使用parent父类引用,解决依赖版本号不确定时自动匹配的问题<parent> &n