All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.core.lang.reflect.FieldUtil Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Copyright (C) 2008 feilong
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.feilong.core.lang.reflect;

import static com.feilong.core.Validator.isNullOrEmpty;
import static com.feilong.core.lang.StringUtil.EMPTY;
import static com.feilong.core.util.CollectionsUtil.selectRejected;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.commons.collections4.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feilong.core.Validate;
import com.feilong.core.util.predicate.BeanPredicateUtil;
import com.feilong.lib.collection4.PredicateUtils;
import com.feilong.lib.lang3.reflect.FieldUtils;
import com.feilong.tools.slf4j.Slf4jUtil;

/**
 * focus on {@link Field} 反射工具类.
 * 
 * 

{@link Field} 相关的几个方法的区别:

* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
字段说明
{@link Class#getDeclaredFields() getDeclaredFields}返回 {@link Field} 对象的一个数组,这些对象反映此 Class 对象所表示的类或接口所声明的所有字段. * *

* 包括公共保护默认(包)访问和私有字段, 但不包括继承的字段. *

* * 返回数组中的元素没有排序,也没有任何特定的顺序.
* 如果该类或接口不声明任何字段,或者此 Class 对象表示一个基本类型、一个数组类或 void,则此方法返回一个长度为 0 的数组.
{@link Class#getFields() getFields}返回一个包含某些 {@link Field} 对象的数组,这些对象反映此 Class 对象所表示的类或接口的所有 可访问公共字段. * *

* 特别地,如果该 Class 对象表示一个类,则此方法返回该类及其所有超类的公共字段.
* 如果该 Class 对象表示一个接口,则此方法返回该接口及其所有超接口的公共字段. *

* *

* 返回数组中的元素没有排序,也没有任何特定的顺序. *

*
* * 如果类或接口没有可访问的公共字段,或者表示一个数组类、一个基本类型或 void,则此方法返回长度为 0 的数组.
* 该方法不反映数组类的隐式长度字段.用户代码应使用 {@link java.lang.reflect.Array} 类的方法来操作数组.
{@link Class#getDeclaredField(String) getDeclaredField}返回一个 {@link Field} 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段.
* 注意,此方法不反映数组类的 length 字段.
{@link Class#getField(String) getField}返回一个 {@link Field} 对象,它反映此 Class 对象所表示的类或接口的指定公共成员字段.
* 要反映的字段由下面的算法确定.
* 设 C 为此对象所表示的类:
* 如果 C 声明一个带有指定名的公共字段,则它就是要反映的字段.
* 如果在第 1 步中没有找到任何字段,则该算法被递归地应用于 C 的每一个直接超接口.直接超接口按其声明顺序进行搜索.
* 如果在第 1、2 两步没有找到任何字段,且 C 有一个超类 S,则在 S 上递归调用该算法.如果 C 没有超类,则抛出 NoSuchFieldException.
*
*
* * @author feilong * @see com.feilong.lib.lang3.reflect.FieldUtils * @see "org.springframework.util.ReflectionUtils" * @since 1.0.7 */ public final class FieldUtil{ /** The Constant LOGGER. */ private static final Logger LOGGER = LoggerFactory.getLogger(FieldUtil.class); /** Don't let anyone instantiate this class. */ private FieldUtil(){ //AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化. //see 《Effective Java》 2nd throw new AssertionError("No " + getClass().getName() + " instances for you!"); } //--------------------------------------------------------------- /** * 获得对象 obj 所有字段的值(不是属性),key是 fieldName,value 是值. * *

说明:

*
*
    *
  1. 是所有字段的值(不是属性)
  2. *
  3. 自动过滤私有并且静态的字段,比如 LOGGER serialVersionUID
  4. *
  5. 返回的map 是 TreeMap,顺序是 field name 的顺序
  6. *
*
* *

示例:

* *
* *
     * User user = new User(12L);
     * LOGGER.debug(JsonUtil.format(FieldUtil.getAllFieldNameAndValueMap(user, "date")));
     * 
* * 返回: * *
     * {
     * "age": null,
     * "id": 12
     * }
     * 
* *
* * @param obj * the obj * @param excludeFieldNames * 需要排除的field names,如果是null或者empty, 那么不会判断 * @return 如果 obj 是null,抛出 {@link NullPointerException}
* 如果 excludeFieldNames 是null或者empty,解析所有的field
* 如果 obj没有字段或者字段都被参数 excludeFieldNames 排除掉了,返回 {@link Collections#emptyMap()}
* @see #getAllFieldList(Class, String...) * @see #getFieldValue(Object, String) */ public static Map getAllFieldNameAndValueMap(Object obj,String...excludeFieldNames){ Validate.notNull(obj, "obj can't be null!"); List fieldList = getAllFieldList(obj.getClass(), excludeFieldNames); if (isNullOrEmpty(fieldList)){ return emptyMap(); } //--------------------------------------------------------------- Map map = new TreeMap<>(); for (Field field : fieldList){ map.put(field.getName(), getFieldValue(obj, field.getName())); } return map; } //--------------------------------------------------------------- /** * 获得 klass 排除某些 excludeFieldNames 之后的字段list. * *

说明:

*
*
    *
  1. 是字段(不是属性)
  2. *
  3. 自动过滤私有并且静态的字段,比如 LOGGER serialVersionUID
  4. *
*
* * @param klass * the klass * @param excludeFieldNames * 需要排除的field names,如果传递过来是null或者empty 那么不会判断 * @return 如果 obj 是null,抛出 {@link NullPointerException}
* 如果 excludeFieldNames 是null或者empty,解析所有的field
* 如果 {@link FieldUtils#getAllFieldsList(Class)} 是null或者empty,返回 {@link Collections#emptyList()}
* 如果 obj没有字段或者字段都被参数 excludeFieldNames 排除掉了,返回 {@link Collections#emptyMap()}
* @see FieldUtils#getAllFieldsList(Class) * @since 1.7.1 */ public static List getAllFieldList(final Class klass,String...excludeFieldNames){ Validate.notNull(klass, "klass can't be null!"); //--------------------------------------------------------------- //获得给定类的所有声明字段 {@link Field},包括所有的parents,包括 public/protect/private/inherited... List fieldList = FieldUtils.getAllFieldsList(klass); if (isNullOrEmpty(fieldList)){ return emptyList(); } //--------------------------------------------------------------- Predicate excludeFieldPredicate = BeanPredicateUtil.containsPredicate("name", excludeFieldNames); Predicate staticPredicate = field -> { int modifiers = field.getModifiers(); // 私有并且静态 一般是log 或者 serialVersionUID boolean isStatic = Modifier.isStatic(modifiers); String pattern = "[{}.{}],modifiers:[{}]{}"; LOGGER.trace(pattern, klass.getSimpleName(), field.getName(), modifiers, isStatic ? " [isStatic]" : EMPTY); return isStatic; }; return selectRejected(fieldList, PredicateUtils.orPredicate(excludeFieldPredicate, staticPredicate)); } //--------------------------------------------------------------- /** * 得到某个对象 owner 的公共字段 fieldName 值. * * @param * the generic type * @param obj * the owner * @param fieldName * the field name * @return 如果 owner 是null,抛出 {@link NullPointerException}
* 如果 fieldName 是null,抛出 {@link NullPointerException}
* 如果 fieldName 是blank,抛出 {@link IllegalArgumentException}
* 如果 obj 中没有 fieldName,抛出 {@link ReflectException}
* @see com.feilong.lib.lang3.reflect.FieldUtils#readField(Object, String, boolean) * @since 1.4.0 * @since 1.9.2 change to private */ @SuppressWarnings("unchecked") private static T getFieldValue(Object obj,String fieldName){ try{ return (T) FieldUtils.readField(obj, fieldName, true); }catch (Exception e){ String pattern = "getFieldValue exception,ownerObj:[{}],fieldName:[{}]"; throw new ReflectException(Slf4jUtil.format(pattern, obj, fieldName), e); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy