com.feilong.core.lang.ObjectUtil Maven / Gradle / Ivy
Show all versions of feilong Show documentation
/*
* 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;
import static com.feilong.core.Validator.isNotNullOrEmpty;
import static com.feilong.core.Validator.isNullOrEmpty;
import static com.feilong.core.lang.StringUtil.EMPTY;
import static com.feilong.core.util.CollectionsUtil.newArrayList;
import static com.feilong.core.util.CollectionsUtil.newHashSet;
import static com.feilong.core.util.MapUtil.newHashMap;
import static com.feilong.core.util.MapUtil.newLinkedHashMap;
import static java.util.Collections.emptyList;
import static java.util.Collections.emptyMap;
import static java.util.Collections.emptySet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import com.feilong.core.Validate;
import com.feilong.core.bean.PropertyUtil;
import com.feilong.core.lang.reflect.ConstructorUtil;
import com.feilong.lib.beanutils.PropertyUtils;
/**
* {@link Object} 工具类.
*
* 判断相等
*
*
*
* - {@link com.feilong.lib.lang3.ObjectUtils#equals(Object, Object)} 支持两个值都是null的情况
* - {@link java.util.Objects#equals(Object, Object)} (since jdk1.7) 也支持两个值都是null的情况
*
*
*
* @author feilong
* @see com.feilong.lib.lang3.ObjectUtils
* @see java.util.Objects
* @since 1.0.0
*/
public final class ObjectUtil{
/** Don't let anyone instantiate this class. */
private ObjectUtil(){
//AssertionError不是必须的. 但它可以避免不小心在类的内部调用构造器. 保证该类在任何情况下都不会被实例化.
//see 《Effective Java》 2nd
throw new AssertionError("No " + getClass().getName() + " instances for you!");
}
/**
* 新建klass实例, 并将fromObj中的 指定属于 includePropertyNames 设置到新建的实例中.
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
*
* public IPage{@code } select(EarphoneforestInfoQueryForm earphoneforestInfoQueryForm){
* Page{@code } page = new Page<>(earphoneforestInfoQueryForm.getPageNo(), earphoneforestInfoQueryForm.getPageSize());
*
* EarphoneforestInfoQueryRequest earphoneforestInfoQueryRequest = new EarphoneforestInfoQueryRequest();
* PropertyUtil.copyProperties(earphoneforestInfoQueryRequest, earphoneforestInfoQueryForm);
*
* IPage{@code } iPage = earphoneforestInfoMapper.select(page, earphoneforestInfoQueryRequest);
* return iPage;
* }
*
*
*
* 可以重构成:
*
*
* public IPage{@code } select(EarphoneforestInfoQueryForm earphoneforestInfoQueryForm){
* Page{@code } page = new Page<>(earphoneforestInfoQueryForm.getPageNo(), earphoneforestInfoQueryForm.getPageSize());
*
* EarphoneforestInfoQueryRequest earphoneforestInfoQueryRequest=newFrom(EarphoneforestInfoQueryRequest.class,earphoneforestInfoQueryForm);
* return earphoneforestInfoMapper.select(page,earphoneforestInfoQueryRequest);
* }
*
*
*
*
* @param
* the generic type
* @param klass
* 可以被实例化的类
* @param fromObj
* 原始对象
* @param includePropertyNames
* 包含的属性数组名字数组,(can be nested/indexed/mapped/combo)
* 如果是null或者empty,将会调用 {@link PropertyUtils#copyProperties(Object, Object)}
*
* - 如果没有传入
includePropertyNames
参数,那么直接调用{@link PropertyUtils#copyProperties(Object, Object)},否则循环调用
* {@link PropertyUtil#getProperty(Object, String)}再{@link PropertyUtil#setProperty(Object, String, Object)}到toObj
对象中
* - 如果传入的
includePropertyNames
,含有 fromObj
没有的属性名字,将会抛出异常
* - 如果传入的
includePropertyNames
,含有 fromObj
有,但是 toObj
没有的属性名字,会抛出异常,see
* {@link com.feilong.lib.beanutils.PropertyUtilsBean#setSimpleProperty(Object, String, Object) copyProperties}
* Line2078
*
* @return 如果 klass
是null,抛出 {@link NullPointerException}
* 如果 fromObj
是null,直接返回 klass 的实例
* 如果 includePropertyNames
是null或者empty,将复制全部属性
* @see com.feilong.core.lang.reflect.ConstructorUtil#newInstance(Class, Object...)
* @see com.feilong.core.bean.PropertyUtil#copyProperties(Object, Object, String...)
* @since 3.1.1
*/
public static T newFrom(final Class klass,Object fromObj,String...includePropertyNames){
Validate.notNull(klass, "klass can't be null!");
T t = ConstructorUtil.newInstance(klass);
if (null == fromObj){
return t;
}
PropertyUtil.copyProperties(t, fromObj, includePropertyNames);
return t;
}
//---------------------------------------------------------------
/**
* 如果 object
是null或者empty,返回默认值 defaultValue
.
*
* 示例:
*
*
*
*
* ObjectUtil.defaultIfNullOrEmpty(null, null) = null
* ObjectUtil.defaultIfNullOrEmpty(null, "") = ""
* ObjectUtil.defaultIfNullOrEmpty(null, "zz") = "zz"
* ObjectUtil.defaultIfNullOrEmpty("abc", *) = "abc"
* ObjectUtil.defaultIfNullOrEmpty(Boolean.TRUE, *) = Boolean.TRUE
*
*
*
*
* 说明:
*
*
* - 使用该方法,可以简化你的代码
* - 如果使用 import static 的特性,代码会更加简洁
* - 如果你只需要判断 null的场景,你可以使用 {@link #defaultIfNull(Object, Object)}
*
*
*
*
* 对下面的代码重构:
*
*
*
*
*
* if (isNotNullOrEmpty(defaultReturnResult.getReturnObject())){
* return (String) defaultReturnResult.getReturnObject();
* }else{
* return "redirect:/";
* }
*
*
*
* 可以重构成:
*
*
* return ObjectUtil.defaultIfNullOrEmpty((String) defaultReturnResult.getReturnObject(), "redirect:/");
*
*
*
*
* 再比如:
*
*
*
*
*
* private void putItemToMap(Map{@code >} map,String categoryName,Item item){
* List{@code - } itemList = map.get(categoryName);
*
* if (isNullOrEmpty(itemList)){
* itemList = new ArrayList{@code <>}();
* }
* itemList.add(item);
* map.put(categoryName, itemList);
* }
*
*
*
* 可以重构成:
*
*
*
* private void putItemToMap(Map{@code >} map,String categoryName,Item item){
* List{@code - } itemList = ObjectUtil.defaultIfNullOrEmpty(map.get(categoryName), new ArrayList{@code
- }());
* itemList.add(item);
* map.put(categoryName, itemList);
* }
*
*
* 当然对于上面的case,你还可以直接调用 {@link com.feilong.core.util.MapUtil#putMultiValue(java.util.Map, Object, Object)}
*
*
*
* @param
* the type of the object
* @param object
* the {@code Object} to test, 可以是 {@code null} or empty
* @param defaultValue
* the default value to return, 可以是 {@code null} or empty
* @return 如果 object
是null或者empty,返回 defaultValue
,否则返回 object
* @see #defaultIfNull(Object, Object)
* @see "org.apache.commons.collections4.ListUtils#defaultIfNull(java.util.List, java.util.List)"
* @since 1.7.2
*/
public static T defaultIfNullOrEmpty(final T object,final T defaultValue){
return isNotNullOrEmpty(object) ? object : defaultValue;
}
//---------------------------------------------------------------
/**
* 如果 object
是null,返回默认值 defaultValue
.
*
*
* ObjectUtil.defaultIfNull(null, null) = null
* ObjectUtil.defaultIfNull(null, "") = ""
* ObjectUtil.defaultIfNull(null, "zz") = "zz"
* ObjectUtil.defaultIfNull("abc", *) = "abc"
* ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
*
*
* @param
* the type of the object
* @param object
* the {@code Object} to test, may be {@code null}
* @param defaultValue
* the default value to return, may be {@code null}
* @return 如果 object
是null,返回 defaultValue
,否则返回 object
* @since 3.0.0
*/
public static T defaultIfNull(final T object,final T defaultValue){
return object != null ? object : defaultValue;
}
//---------------------------------------------------------------
/**
* 如果 str
是null,返回默认值 {@link com.feilong.core.lang.StringUtil#EMPTY}.
*
*
* ObjectUtil.defaultEmptyStringIfNull(null) = EMPTY;
* ObjectUtil.defaultEmptyStringIfNull("a") = "a";
*
*
* 适合场景:
*
*
*
* 比如以下字符串拼接的代码:
*
*
*
*
* return Slf4jUtil.format(
* "{}-{} {}_{}_{}.svg", //
* villageConfig.getId(),
* defaultIfNull(categoryId, EMPTY),
* defaultIfNull(villageConfig.getTitle(), EMPTY),
* defaultIfNull(categoryName, EMPTY),
* villageQrCodeGeneratorVO.getDataTime());
*
*
*
* 可以重构成:
*
*
* return Slf4jUtil.format(
* "{}-{} {}_{}_{}.svg", //
* villageConfig.getId(),
* defaultEmptyStringIfNull(categoryId),
* defaultEmptyStringIfNull(villageConfig.getTitle()),
* defaultEmptyStringIfNull(categoryName),
* villageQrCodeGeneratorVO.getDataTime());
*
*
*
*
* @param str
* the str
* @return 如果 str
是null,返回默认值 {@link com.feilong.core.lang.StringUtil#EMPTY}.
* @since 3.3.6
* @apiNote 实现代码:
* defaultIfNull(str, EMPTY);
*/
public static String defaultEmptyStringIfNull(final String str){
return defaultIfNull(str, EMPTY);
}
//---------------------------------------------------------------
/**
* 如果 list
是null,返回默认值 {@link java.util.Collections#emptyList()}.
*
*
* ObjectUtil.defaultEmptyListIfNull(null) = emptyList();
* ObjectUtil.defaultEmptyListIfNull(toList(1)) = toList(1);
*
*
* @param
* the type of the object
* @param list
* the {@code Object} to test, may be {@code null}
* @return 如果 list
是null,返回默认值 {@link java.util.Collections#emptyList()}.
* @since 3.3.5
*/
public static List defaultEmptyListIfNull(final List list){
return defaultIfNull(list, emptyList());
}
/**
* 如果 set
是null,返回默认值 {@link java.util.Collections#emptySet()}.
*
*
* ObjectUtil.defaultEmptySetIfNull(null) = emptySet();
* ObjectUtil.defaultEmptySetIfNull(toSet(1)) = toSet(1);
*
*
* @param
* the type of the object
* @param set
* the {@code Object} to test, may be {@code null}
* @return 如果 set
是null,返回默认值 {@link java.util.Collections#emptySet()}.
* @since 3.3.5
*/
public static Set defaultEmptySetIfNull(final Set set){
return defaultIfNull(set, emptySet());
}
/**
* 如果 map
是null,返回默认值 {@link java.util.Collections#emptyMap()}.
*
*
* ObjectUtil.defaultEmptyMapIfNull(null) = emptyMap();
* ObjectUtil.defaultEmptyMapIfNull(toMap("name", "zhangfei")) = toMap("name", "zhangfei");
*
*
* @param
* the key type
* @param
* the value type
* @param map
* the map
* @return 如果 map
是null,返回默认值 {@link java.util.Collections#emptyMap()}.
* @since 3.3.5
*/
public static Map defaultEmptyMapIfNull(final Map map){
return defaultIfNull(map, emptyMap());
}
//---------------------------------------------------------------
/**
* 如果 list
是null,返回默认值 {@link com.feilong.core.util.CollectionsUtil#newArrayList()}.
*
*
* ObjectUtil.defaultNewArrayListIfNull(null) = newArrayList();
* ObjectUtil.defaultNewArrayListIfNull(toList(1)) = toList(1);
*
*
* @param
* the type of the object
* @param list
* the {@code Object} to test, may be {@code null}
* @return 如果 list
是null,返回默认值 {@link com.feilong.core.util.CollectionsUtil#newArrayList()}.
* @since 3.3.6
*/
public static List defaultNewArrayListIfNull(final List list){
return defaultIfNull(list, newArrayList());
}
/**
* 如果 set
是null,返回默认值 {@link com.feilong.core.util.CollectionsUtil#newHashSet()}.
*
*
* ObjectUtil.defaultNewHashSetIfNull(null) = newHashSet();
* ObjectUtil.defaultNewHashSetIfNull(toSet(1)) = toSet(1);
*
*
* @param
* the type of the object
* @param set
* the {@code Object} to test, may be {@code null}
* @return 如果 set
是null,返回默认值 {@link com.feilong.core.util.CollectionsUtil#newHashSet()}.
* @since 3.3.6
*/
public static Set defaultNewHashSetIfNull(final Set set){
return defaultIfNull(set, newHashSet());
}
/**
* 如果 map
是null,返回默认值 {@link com.feilong.core.util.MapUtil#newHashMap()}.
*
*
* ObjectUtil.defaultNewHashMapIfNull(null) = newHashMap();
* ObjectUtil.defaultNewHashMapIfNull(toMap("name", "zhangfei")) = toMap("name", "zhangfei");
*
*
* @param
* the key type
* @param
* the value type
* @param map
* the map
* @return 如果 map
是null,返回默认值 {@link com.feilong.core.util.MapUtil#newHashMap()}.
* @since 3.3.6
*/
public static Map defaultNewHashMapIfNull(final Map map){
return defaultIfNull(map, newHashMap());
}
/**
* 如果 map
是null,返回默认值 {@link com.feilong.core.util.MapUtil#newLinkedHashMap()}.
*
*
* ObjectUtil.defaultNewLinkedHashMapIfNull(null) = newLinkedHashMap();
* ObjectUtil.defaultNewLinkedHashMapIfNull(toMap("name", "zhangfei")) = toMap("name", "zhangfei");
*
*
* @param
* the key type
* @param
* the value type
* @param map
* the map
* @return 如果 map
是null,返回默认值 {@link com.feilong.core.util.MapUtil#newLinkedHashMap()}.
* @since 3.3.6
*/
public static Map defaultNewLinkedHashMapIfNull(final Map map){
return defaultIfNull(map, newLinkedHashMap());
}
//---------------------------------------------------------------
/**
* 如果 pageNo
是null或者{@code <}1,返回默认值 1
.
*
*
* 用于分页处理页面的场景
*
*
*
* ObjectUtil.defaultPageNo(null) = 1
* ObjectUtil.defaultPageNo(0 ) = 1
* ObjectUtil.defaultPageNo(8) = 8
*
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
*
* page = defaultIfNull(page, 1);
* searchQuery.setPageIndex(page <= 0 ? 1 : page);
*
*
*
* 可以重构成:
*
*
* searchQuery.setPageIndex(defaultPageNo(page));
*
*
*
*
* @param pageNo
* the page no
* @return 如果 pageNo
是null或者{@code <}1,返回 1
,否则返回 pageNo
* @since 3.3.2
*/
public static Integer defaultPageNo(Integer pageNo){
return defaultIfNullOrLessThanOne(pageNo, 1);
}
/**
* 如果 i
是null或者{@code <}0,返回默认值 0
.
*
*
* ObjectUtil.defaultZero(null) = 0
* ObjectUtil.defaultZero(-1) = 0
* ObjectUtil.defaultZero(0) = 0
* ObjectUtil.defaultZero(8) = 8
*
*
* @param i
* i
* @return 如果 i
是null或者{@code <}0,返回 0
,否则返回 i
* @since 4.0.1
*/
public static Integer defaultZero(Integer i){
if (null == i){
return 0;
}
if (i < 0){
return 0;
}
return i;
}
/**
* 如果 i
是null或者{@code <}1,返回默认值 defaultValue
.
*
*
* 常用于分页处理页面的场景
*
*
*
* ObjectUtil.defaultIfNullOrLessThanOne(null, null) = null
* ObjectUtil.defaultIfNullOrLessThanOne(null, 1) = 1
* ObjectUtil.defaultIfNullOrLessThanOne(0, 2) = 2
* ObjectUtil.defaultIfNullOrLessThanOne(8, 2) = 8
*
*
* 重构:
*
*
*
* 对于以下代码:
*
*
*
*
* page = defaultIfNull(page, 1);
* searchQuery.setPageIndex(page <= 0 ? 1 : page);
*
*
*
* 可以重构成:
*
*
* searchQuery.setPageIndex(defaultIfNullOrLessThanOne(page, 1));
*
*
*
*
* @param i
* the i
* @param defaultValue
* the default value to return, may be {@code null}
* @return 如果 i
是null或者{@code <}1,返回 defaultValue
,否则返回 object
* @since 3.3.2
*/
public static Integer defaultIfNullOrLessThanOne(Integer i,Integer defaultValue){
if (null == i){
return defaultValue;
}
if (i < 1){
return defaultValue;
}
return i;
}
//---------------------------------------------------------------
/**
* 判断指定的对象 object
是否是数组.
*
* 说明:
*
*
* - 支持判断原始类型数组
primitive
和包装类型数组
*
*
*
* 示例:
*
*
*
*
* int[] i = {};
* ObjectUtil.isArray(i); =true
*
* ObjectUtil.isArray(new int[] { 1, 2, 3 }); =true
*
* ObjectUtil.isArray(new Integer[0]); =true
* ObjectUtil.isArray(new String[0]); =true
*
*
*
*
* instanceof
和 {@link java.lang.Class#isArray()}的区别:
*
*
*
* 通常使用instanceof
操作符去判断一个对象 object
是否是数组 array
.
* 在JVM层次,instanceof
操作符 translates to a specific "instanceof" byte code, which is highly optimized in most JVM
* implementations.
*
*
*
* 而反射的方法(getClass().isArray()) is compiled to two separate "invokevirtual" instructions.
* The more generic optimizations applied by the JVM to these may not be as fast as the hand-tuned optimizations inherent in the
* "instanceof" instruction.
*
*
*
* 有两种特殊情况: null references 和 primitive arrays.
*
*
*
*
*
*
* instanceof
* getClass().isArray()
*
*
*
* null reference
* false
* NullPointerException
*
*
*
* 原始类型数组primitive array
* false
* true
*
*
*
*
*
* @param object
* the object
* @return 如果 object
是null,抛出 {@link NullPointerException}
* @see Java array reflection: isArray
* vs. instanceof
* @see How to see if
* an object is an array without using reflection?
* @since 1.3.0
*/
public static boolean isArray(Object object){
Validate.notNull(object, "object can't be null!");
return object.getClass().isArray();
}
//---------------------------------------------------------------
/**
* 判断指定的对象 object
是否是原生类型数组.
*
* 示例:
*
*
*
*
*
* ObjectUtil.isPrimitiveArray(1) = false
* ObjectUtil.isPrimitiveArray(1L) = false
* ObjectUtil.isPrimitiveArray("1") = false
*
*
* ObjectUtil.isPrimitiveArray(new int[] {}) = true
* ObjectUtil.isPrimitiveArray(new int[] { 1, 2 }) = true
* ObjectUtil.isPrimitiveArray(new byte[] { 1, 2 }) = true
*
* ObjectUtil.isPrimitiveArray(new String[] { "1", "2" }) = false
*
*
*
*
* @param object
* the object
* @return 如果 object
是null,抛出 {@link NullPointerException}
* @since 1.8.4
*/
public static boolean isPrimitiveArray(Object object){
Validate.notNull(object, "object can't be null!");
return isArray(object) && object.getClass().getComponentType().isPrimitive();//原始型的
}
//---------------------------------------------------------------
/**
*
* 对比 given {@code t} to a vararg of {@code searchTargets},
* 如果 {@code true} if the {@code t} is equal to any of the {@code searchTargets}.
*
*
*
* 比 apache commons-lang3 StringUtils#equalsAny 适用面更广
*
*
*
* ObjectUtil.equalsAny(null, (CharSequence[]) null) = false
* ObjectUtil.equalsAny(null, null, null) = true
* ObjectUtil.equalsAny(null, "abc", "def") = false
* ObjectUtil.equalsAny("abc", null, "def") = false
* ObjectUtil.equalsAny("abc", "abc", "def") = true
* ObjectUtil.equalsAny("abc", "ABC", "DEF") = false
* ObjectUtil.equalsAny(5, 5, 6) = true
*
*
* @param
* the generic type
* @param t
* to compare, may be {@code null}.
* @param searchTargets
* a vararg of t, may be {@code null}.
* @return {@code true} 如果 t is equal to any other element of {@code searchTargets};
* {@code false} if {@code searchTargets} is null or contains no matches.
* @see com.feilong.lib.lang3.StringUtils#equalsAny(CharSequence, CharSequence...)
* @since 3.1.0
*/
@SafeVarargs
public static boolean equalsAny(T t,T...searchTargets){
if (isNullOrEmpty(searchTargets)){
return false;
}
//---------------------------------------------------------------
for (T target : searchTargets){
if (Objects.equals(t, target)){
return true;
}
}
return false;
}
}