Java8通過Function獲取欄位名(獲取實體類的欄位名稱)
看似很雞肋其實在某些特殊場景還是比較有用的。
比如你將實體類轉Map或者拿到一個Map結果的時候,你是怎麼獲取某個map的key和value。
方法一:
聲明 String key1="name"; key為 key1,value 為map.get(key1);
1 Map<String,Object> map=new HashMap<>(); 2 map.put("aaa",1); 3 4 //獲取map的key 和value 5 //key 為key1 6 String key1="aaa"; 7 //value 為 map.get(key1) 8 map.get(key1);
然後好像日常使用中也沒有其他的方法了,下面將帶來另外一種使用方法,話不多說直接上程式碼
1 import java.io.Serializable; 2 import java.lang.annotation.ElementType; 3 import java.lang.annotation.Retention; 4 import java.lang.annotation.RetentionPolicy; 5 import java.lang.annotation.Target; 6 import java.lang.invoke.SerializedLambda; 7 import java.lang.reflect.Field; 8 import java.lang.reflect.InvocationTargetException; 9 import java.lang.reflect.Method; 10 import java.util.function.Function; 11 12 /** 13 * Java8通過Function函數獲取欄位名稱(獲取實體類的欄位名稱) 14 * @see ColumnUtil#main(java.lang.String[]) 使用示例 15 * @author jx 16 */ 17 public class ColumnUtil { 18 19 /** 20 * 使Function獲取序列化能力 21 */ 22 @FunctionalInterface 23 public interface SFunction<T, R> extends Function<T, R>, Serializable { 24 } 25 26 /** 27 * 欄位名註解,聲明表欄位 28 */ 29 @Target(ElementType.FIELD) 30 @Retention(RetentionPolicy.RUNTIME) 31 public @interface TableField { 32 String value() default ""; 33 } 34 35 //默認配置 36 static String defaultSplit = ""; 37 static Integer defaultToType = 0; 38 39 /** 40 * 獲取實體類的欄位名稱(實體聲明的欄位名稱) 41 */ 42 public static <T> String getFieldName(SFunction<T, ?> fn) { 43 return getFieldName(fn, defaultSplit); 44 } 45 46 /** 47 * 獲取實體類的欄位名稱 48 * @param split 分隔符,多個字母自定義分隔符 49 */ 50 public static <T> String getFieldName(SFunction<T, ?> fn, String split) { 51 return getFieldName(fn, split, defaultToType); 52 } 53 54 /** 55 * 獲取實體類的欄位名稱 56 * @param split 分隔符,多個字母自定義分隔符 57 * @param toType 轉換方式,多個字母以大小寫方式返回 0.不做轉換 1.大寫 2.小寫 58 */ 59 public static <T> String getFieldName(SFunction<T, ?> fn, String split, Integer toType) { 60 SerializedLambda serializedLambda = getSerializedLambda(fn); 61 62 // 從lambda資訊取出method、field、class等 63 String fieldName = serializedLambda.getImplMethodName().substring("get".length()); 64 fieldName = fieldName.replaceFirst(fieldName.charAt(0) + "", (fieldName.charAt(0) + "").toLowerCase()); 65 Field field; 66 try { 67 field = Class.forName(serializedLambda.getImplClass().replace("/", ".")).getDeclaredField(fieldName); 68 } catch (ClassNotFoundException | NoSuchFieldException e) { 69 throw new RuntimeException(e); 70 } 71 72 // 從field取出欄位名,可以根據實際情況調整 73 TableField tableField = field.getAnnotation(TableField.class); 74 if (tableField != null && tableField.value().length() > 0) { 75 return tableField.value(); 76 } else { 77 78 //0.不做轉換 1.大寫 2.小寫 79 switch (toType) { 80 case 1: 81 return fieldName.replaceAll("[A-Z]", split + "$0").toUpperCase(); 82 case 2: 83 return fieldName.replaceAll("[A-Z]", split + "$0").toLowerCase(); 84 default: 85 return fieldName.replaceAll("[A-Z]", split + "$0"); 86 } 87 88 } 89 90 } 91 92 private static <T> SerializedLambda getSerializedLambda(SFunction<T, ?> fn) { 93 // 從function取出序列化方法 94 Method writeReplaceMethod; 95 try { 96 writeReplaceMethod = fn.getClass().getDeclaredMethod("writeReplace"); 97 } catch (NoSuchMethodException e) { 98 throw new RuntimeException(e); 99 } 100 101 // 從序列化方法取出序列化的lambda資訊 102 boolean isAccessible = writeReplaceMethod.isAccessible(); 103 writeReplaceMethod.setAccessible(true); 104 SerializedLambda serializedLambda; 105 try { 106 serializedLambda = (SerializedLambda) writeReplaceMethod.invoke(fn); 107 } catch (IllegalAccessException | InvocationTargetException e) { 108 throw new RuntimeException(e); 109 } 110 writeReplaceMethod.setAccessible(isAccessible); 111 return serializedLambda; 112 } 113 114 115 /** 116 * 測試用戶實體類 117 */ 118 public static class TestUserDemo implements Serializable { 119 120 private static final long serialVersionUID = 1L; 121 122 private String loginName; 123 private String name; 124 private String companySimpleName; 125 126 @ColumnUtil.TableField("nick") 127 private String nickName; 128 129 public String getLoginName() { 130 return loginName; 131 } 132 133 public void setLoginName(String loginName) { 134 this.loginName = loginName; 135 } 136 137 public String getNickName() { 138 return nickName; 139 } 140 141 public void setNickName(String nickName) { 142 this.nickName = nickName; 143 } 144 145 public static long getSerialVersionUID() { 146 return serialVersionUID; 147 } 148 149 public String getName() { 150 return name; 151 } 152 153 public void setName(String name) { 154 this.name = name; 155 } 156 157 public String getCompanySimpleName() { 158 return companySimpleName; 159 } 160 161 public void setCompanySimpleName(String companySimpleName) { 162 this.companySimpleName = companySimpleName; 163 } 164 } 165 166 167 /** 168 * 參考示例 169 */ 170 public static void main(String[] args) { 171 172 //實體類原欄位名稱返回 173 System.out.println(); 174 System.out.println("實體類原欄位名稱返回"); 175 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getLoginName)); 176 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getNickName)); 177 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName)); 178 179 System.out.println(); 180 System.out.println("實體類欄位名稱增加分隔符"); 181 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_")); 182 183 System.out.println(); 184 System.out.println("實體類欄位名稱增加分隔符 + 大小寫"); 185 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 0)); 186 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 1)); 187 System.out.println("欄位名:" + ColumnUtil.getFieldName(TestUserDemo::getCompanySimpleName, "_", 2)); 188 189 190 } 191 192 193 }