From 55fa1812a9b5d24337569f2c8fed30e27111d8c9 Mon Sep 17 00:00:00 2001
From: huangchengxing <841396397@qq.com>
Date: Wed, 31 Aug 2022 13:22:00 +0800
Subject: [PATCH] fix docs and test cases
---
.../java/cn/hutool/core/util/ObjUtil.java | 176 +++++++++--------
.../java/cn/hutool/core/util/ObjUtilTest.java | 183 ++++++++++++++----
2 files changed, 241 insertions(+), 118 deletions(-)
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java
index 3d88ceb10..81a45da6b 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ObjUtil.java
@@ -1,5 +1,6 @@
package cn.hutool.core.util;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.iter.IterUtil;
import cn.hutool.core.comparator.CompareUtil;
import cn.hutool.core.convert.Convert;
@@ -9,15 +10,13 @@ import cn.hutool.core.map.MapUtil;
import cn.hutool.core.math.NumberUtil;
import cn.hutool.core.reflect.ClassUtil;
import cn.hutool.core.reflect.MethodUtil;
+import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.text.StrUtil;
+import java.io.Serializable;
import java.lang.reflect.Array;
import java.math.BigDecimal;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Objects;
+import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
@@ -29,13 +28,12 @@ import java.util.function.Supplier;
public class ObjUtil {
/**
- * 比较两个对象是否相等。
- * 相同的条件有两个,满足其一即可:
- *
- * - obj1 == null && obj2 == null
- * - obj1.equals(obj2)
- * - 如果是BigDecimal比较,0 == obj1.compareTo(obj2)
- *
+ * 比较两个对象是否相等,满足下述任意条件即返回{@code true}:
+ *
+ * - 若两对象皆为{@link BigDecimal},且满足{@code 0 == obj1.compareTo(obj2)}
+ * - {@code obj1 == null && obj2 == null}
+ * - {@code obj1.equals(obj2)}
+ *
*
* @param obj1 对象1
* @param obj2 对象2
@@ -50,27 +48,27 @@ public class ObjUtil {
}
/**
- * 比较两个对象是否不相等。
+ * 比较两个对象是否不相等
*
* @param obj1 对象1
* @param obj2 对象2
* @return 是否不等
* @since 3.0.7
+ * @see #equals(Object, Object)
*/
public static boolean notEquals(final Object obj1, final Object obj2) {
return false == equals(obj1, obj2);
}
/**
- * 计算对象长度,如果是字符串调用其length函数,集合类调用其size函数,数组调用其length属性,其他可遍历对象遍历计算长度
- * 支持的类型包括:
+ * 计算对象长度,支持类型包括:
*
- * - CharSequence
- * - Map
- * - Iterator
- * - Iterable
- * - Enumeration
- * - Array
+ * - {@code null}:默认返回{@code 0};
+ * - 数组:返回数组长度;
+ * - {@link CharSequence}:返回{@link CharSequence#length()};
+ * - {@link Collection}:返回{@link Collection#size()};
+ * - {@link Iterator}或{@link Iterable}:可迭代的元素数量;
+ * - {@link Enumeration}:返回可迭代的元素数量;
*
*
* @param obj 被计算长度的对象
@@ -100,6 +98,9 @@ public class ObjUtil {
}
return count;
}
+ if (obj.getClass().isArray()) {
+ return Array.getLength(obj);
+ }
if (obj instanceof Enumeration) {
final Enumeration> enumeration = (Enumeration>) obj;
count = 0;
@@ -109,23 +110,21 @@ public class ObjUtil {
}
return count;
}
- if (obj.getClass().isArray()) {
- return Array.getLength(obj);
- }
return -1;
}
/**
- * 对象中是否包含元素
- * 支持的对象类型包括:
+ * 检查{@code obj}中是否包含{@code element},若{@code obj}为{@code null},则直接返回{@code false}。
+ * 支持类型包括:
*
- * - String
- * - Collection
- * - Map
- * - Iterator
- * - Iterable
- * - Enumeration
- * - Array
+ * - {@code null}:默认返回{@code false};
+ * - {@link String}:等同{@link String#contains(CharSequence)};
+ * - {@link Collection}:等同{@link Collection#contains(Object)};
+ * - {@link Map}:等同{@link Map#containsValue(Object)};
+ * -
+ * {@link Iterator}、{@link Iterable}、{@link Enumeration}或数组:
+ * 等同于遍历后对其元素调用{@link #equals(Object, Object)}方法;
+ *
*
*
* @param obj 对象
@@ -182,12 +181,7 @@ public class ObjUtil {
}
/**
- * 检查对象是否为null
- * 判断标准为:
- *
- *
- * 1. == null
- *
+ * 检查对象是否为{@code null}
*
* @param obj 对象
* @return 是否为null
@@ -197,7 +191,7 @@ public class ObjUtil {
}
/**
- * 检查对象是否不为null
+ * 检查对象是否不为{@code null}
*
* @param obj 对象
* @return 是否为null
@@ -207,19 +201,26 @@ public class ObjUtil {
}
/**
- * 判断指定对象是否为空,支持:
- *
- *
- * 1. CharSequence
- * 2. Map
- * 3. Iterable
- * 4. Iterator
- * 5. Array
- *
+ * 判断指定对象是否为空,支持类型包括:
+ *
+ * - {@code null}:默认返回{@code true};
+ * - 数组:等同于{@link ArrayUtil#isEmpty(Object)};
+ * - {@link CharSequence}:等同于{@link CharSequenceUtil#isEmpty(CharSequence)};
+ * - {@link Collection}:等同于{@link CollUtil#isEmpty(Collection)};
+ * - {@link Map}:等同于{@link MapUtil#isEmpty(Map)};
+ * -
+ * {@link Iterator}或{@link Iterable}:等同于{@link IterUtil#isEmpty(Iterator)}、
+ * {@link IterUtil#isEmpty(Iterable)};
+ *
+ *
*
* @param obj 被判断的对象
* @return 是否为空,如果类型不支持,返回false
* @since 4.5.7
+ * @see StrUtil#isEmpty(CharSequence)
+ * @see MapUtil#isEmpty(Map)
+ * @see IterUtil#isEmpty(Iterable)
+ * @see IterUtil#isEmpty(Iterator)
*/
@SuppressWarnings("rawtypes")
public static boolean isEmpty(final Object obj) {
@@ -229,7 +230,9 @@ public class ObjUtil {
if (obj instanceof CharSequence) {
return StrUtil.isEmpty((CharSequence) obj);
- } else if (obj instanceof Map) {
+ } else if(obj instanceof Collection){
+ return CollUtil.isEmpty((Collection)obj);
+ }else if (obj instanceof Map) {
return MapUtil.isEmpty((Map) obj);
} else if (obj instanceof Iterable) {
return IterUtil.isEmpty((Iterable) obj);
@@ -243,34 +246,26 @@ public class ObjUtil {
}
/**
- * 判断指定对象是否为非空,支持:
- *
- *
- * 1. CharSequence
- * 2. Map
- * 3. Iterable
- * 4. Iterator
- * 5. Array
- *
+ * 判断指定对象是否为非空
*
* @param obj 被判断的对象
* @return 是否为空,如果类型不支持,返回true
* @since 4.5.7
+ * @see #isEmpty(Object)
*/
public static boolean isNotEmpty(final Object obj) {
return false == isEmpty(obj);
}
/**
- * 如果给定对象为{@code null}返回默认值
- *
- *
- * ObjectUtil.defaultIfNull(null, null) = null
- * ObjectUtil.defaultIfNull(null, "") = ""
- * ObjectUtil.defaultIfNull(null, "zz") = "zz"
- * ObjectUtil.defaultIfNull("abc", *) = "abc"
- * ObjectUtil.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
- *
+ * 如果给定对象为{@code null}返回默认值
+ *
{@code
+ * ObjectUtil.defaultIfNull(null, null); // = null
+ * ObjectUtil.defaultIfNull(null, ""); // = ""
+ * ObjectUtil.defaultIfNull(null, "zz"); // = "zz"
+ * ObjectUtil.defaultIfNull("abc", *); // = "abc"
+ * ObjectUtil.defaultIfNull(Boolean.TRUE, *); // = Boolean.TRUE
+ * }
*
* @param 对象类型
* @param object 被检查对象,可能为{@code null}
@@ -333,14 +328,20 @@ public class ObjUtil {
}
/**
- * 克隆对象
- * 如果对象实现Cloneable接口,调用其clone方法
- * 如果实现Serializable接口,执行深度克隆
- * 否则返回{@code null}
+ * 克隆对象
+ *
+ * - 如果对象是数组,则等同于{@link ArrayUtil#clone(Object)};
+ * - 如果对象实现了{@link Cloneable}接口,调用其{@link Cloneable#clone()}方法;
+ * - 如果对象实现了{@link Serializable}接口,执行深度克隆;
+ * - 不符合上述任意情况则返回{@code null};
+ *
*
* @param 对象类型
* @param obj 被克隆对象
* @return 克隆后的对象
+ * @see ArrayUtil#clone(Object)
+ * @see Object#clone()
+ * @see #cloneByStream(Object)
*/
public static T clone(final T obj) {
T result = ArrayUtil.clone(obj);
@@ -360,6 +361,7 @@ public class ObjUtil {
* @param 对象类型
* @param obj 对象
* @return 克隆后或原对象
+ * @see #clone(Object)
*/
public static T cloneIfPossible(final T obj) {
T clone = null;
@@ -373,12 +375,13 @@ public class ObjUtil {
/**
* 序列化后拷贝流的方式克隆
- * 对象必须实现Serializable接口
+ * 若对象未实现{@link Serializable}接口则默认返回{@code null}
*
* @param 对象类型
* @param obj 被克隆对象
* @return 克隆后的对象
* @throws UtilException IO异常和ClassNotFoundException封装
+ * @see SerializeUtil#clone(Object)
*/
public static T cloneByStream(final T obj) {
return SerializeUtil.clone(obj);
@@ -399,12 +402,15 @@ public class ObjUtil {
}
/**
- * 检查是否为有效的数字
- * 检查Double和Float是否为无限大,或者Not a Number
- * 非数字类型和Null将返回true
+ * 检查是否为有效的数字,若对象不为{@link Number},则直接返回{@code true},否则:
+ *
+ * - 若对象类型为{@link Double},则检查{@link Double#isInfinite()}或{@link Double#isNaN()};
+ * - 若对象类型为{@link Float},则检查{@link Float#isInfinite()}或{@link Float#isNaN()};
+ *
*
* @param obj 被检查类型
* @return 检查结果,非数字类型和Null将返回true
+ * @see NumberUtil#isValidNumber(Number)
*/
public static boolean isValidIfNumber(final Object obj) {
if (obj instanceof Number) {
@@ -454,7 +460,7 @@ public class ObjUtil {
}
/**
- * 获得给定类的第一个泛型参数
+ * 获得给定类指定下标的泛型参数
*
* @param obj 被检查的对象
* @param index 泛型类型的索引号,即第几个泛型类型
@@ -466,16 +472,17 @@ public class ObjUtil {
}
/**
- * 将Object转为String
- * 策略为:
- *
- * 1、null转为"null"
- * 2、调用Convert.toStr(Object)转换
- *
+ * 将对象转为字符串
+ *
+ * - 若对象为{@code null},则返回“null”;
+ * - 若对象为{@link Map},则返回{@link Map#toString()};
+ * - 若对象为其他类型,则调用{@link Convert#toStr(Object)}进行转换;
+ *
*
* @param obj Bean对象
- * @return Bean所有字段转为Map后的字符串
+ * @return 转换后的字符串
* @since 3.2.0
+ * @see Convert#toStr(Object)
*/
public static String toString(final Object obj) {
if (null == obj) {
@@ -484,7 +491,6 @@ public class ObjUtil {
if (obj instanceof Map) {
return obj.toString();
}
-
return Convert.toStr(obj);
}
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java
index dd920ee8b..b4c720f09 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ObjUtilTest.java
@@ -1,17 +1,23 @@
package cn.hutool.core.util;
import cn.hutool.core.collection.ListUtil;
-import cn.hutool.core.exceptions.CloneRuntimeException;
+import lombok.EqualsAndHashCode;
+import lombok.RequiredArgsConstructor;
import org.junit.Assert;
import org.junit.Test;
+import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
-import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
+/**
+ * test for {@link ObjUtil}
+ */
public class ObjUtilTest {
@Test
@@ -56,43 +62,49 @@ public class ObjUtilTest {
final Iterable list = ListUtil.of(1, 2, 3);
Assert.assertEquals(3, ObjUtil.length(list));
+ Assert.assertEquals(3, ObjUtil.length(Arrays.asList(1, 2, 3).iterator()));
}
@Test
public void containsTest(){
- final int[] array = new int[]{1,2,3,4,5};
-
- final boolean contains = ObjUtil.contains(array, 1);
- Assert.assertTrue(contains);
+ Assert.assertTrue(ObjUtil.contains(new int[]{1,2,3,4,5}, 1));
+ Assert.assertFalse(ObjUtil.contains(null, 1));
+ Assert.assertTrue(ObjUtil.contains("123", "3"));
+ Map map = new HashMap<>();
+ map.put(1, 1);
+ map.put(2, 2);
+ Assert.assertTrue(ObjUtil.contains(map, 1));
+ Assert.assertTrue(ObjUtil.contains(Arrays.asList(1, 2, 3).iterator(), 2));
}
@Test
- public void cloneTest() {
- final Obj obj = new Obj();
- final Obj obj2 = ObjUtil.clone(obj);
- Assert.assertEquals("OK", obj2.doSomeThing());
- }
-
- static class Obj implements Cloneable {
- public String doSomeThing() {
- return "OK";
- }
-
- @Override
- public Obj clone() {
- try {
- return (Obj) super.clone();
- } catch (final CloneNotSupportedException e) {
- throw new CloneRuntimeException(e);
- }
- }
+ public void isNullTest() {
+ Assert.assertTrue(ObjUtil.isNull(null));
}
@Test
- public void toStringTest() {
- final ArrayList strings = ListUtil.of("1", "2");
- final String result = ObjUtil.toString(strings);
- Assert.assertEquals("[1, 2]", result);
+ public void isNotNullTest() {
+ Assert.assertFalse(ObjUtil.isNotNull(null));
+ }
+
+ @Test
+ public void isEmptyTest() {
+ Assert.assertTrue(ObjUtil.isEmpty(null));
+ Assert.assertTrue(ObjUtil.isEmpty(new int[0]));
+ Assert.assertTrue(ObjUtil.isEmpty(""));
+ Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyList()));
+ Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyMap()));
+ Assert.assertTrue(ObjUtil.isEmpty(Collections.emptyIterator()));
+ }
+
+ @Test
+ public void isNotEmptyTest() {
+ Assert.assertFalse(ObjUtil.isNotEmpty(null));
+ Assert.assertFalse(ObjUtil.isNotEmpty(new int[0]));
+ Assert.assertFalse(ObjUtil.isNotEmpty(""));
+ Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyList()));
+ Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyMap()));
+ Assert.assertFalse(ObjUtil.isNotEmpty(Collections.emptyIterator()));
}
@Test
@@ -113,6 +125,48 @@ public class ObjUtilTest {
Assert.assertSame(val2, ObjUtil.defaultIfNull(null, Function.identity(), val2));
}
+ @Test
+ public void cloneTest() {
+ Assert.assertNull(ObjUtil.clone(null));
+
+ final CloneableBean cloneableBean1 = new CloneableBean(1);
+ final CloneableBean cloneableBean2 = ObjUtil.clone(cloneableBean1);
+ Assert.assertEquals(cloneableBean1, cloneableBean2);
+
+ final SerializableBean serializableBean1 = new SerializableBean(2);
+ final SerializableBean serializableBean2 = ObjUtil.clone(serializableBean1);
+ Assert.assertEquals(serializableBean1, serializableBean2);
+
+ final Bean bean1 = new Bean(3);
+ Assert.assertNull(ObjUtil.clone(bean1));
+ }
+
+ @Test
+ public void cloneIfPossibleTest() {
+ Assert.assertNull(ObjUtil.clone(null));
+
+ final CloneableBean cloneableBean1 = new CloneableBean(1);
+ Assert.assertEquals(cloneableBean1, ObjUtil.cloneIfPossible(cloneableBean1));
+
+ final SerializableBean serializableBean1 = new SerializableBean(2);
+ Assert.assertEquals(serializableBean1, ObjUtil.cloneIfPossible(serializableBean1));
+
+ final Bean bean1 = new Bean(3);
+ Assert.assertSame(bean1, ObjUtil.cloneIfPossible(bean1));
+
+ final ExceptionCloneableBean exceptionBean1 = new ExceptionCloneableBean(3);
+ Assert.assertSame(exceptionBean1, ObjUtil.cloneIfPossible(exceptionBean1));
+ }
+
+ @Test
+ public void cloneByStreamTest() {
+ Assert.assertNull(ObjUtil.cloneByStream(null));
+ Assert.assertNull(ObjUtil.cloneByStream(new CloneableBean(1)));
+ final SerializableBean serializableBean1 = new SerializableBean(2);
+ Assert.assertEquals(serializableBean1, ObjUtil.cloneByStream(serializableBean1));
+ Assert.assertNull(ObjUtil.cloneByStream(new Bean(1)));
+ }
+
@Test
public void isBasicTypeTest(){
final int a = 1;
@@ -121,9 +175,72 @@ public class ObjUtilTest {
}
@Test
- public void cloneIfPossibleTest() {
- final String a = "a";
- final String a2 = ObjUtil.cloneIfPossible(a);
- Assert.assertNotSame(a, a2);
+ public void isValidIfNumberTest() {
+ Assert.assertTrue(ObjUtil.isValidIfNumber(null));
+ Assert.assertFalse(ObjUtil.isValidIfNumber(Double.NEGATIVE_INFINITY));
+ Assert.assertFalse(ObjUtil.isValidIfNumber(Double.NaN));
+ Assert.assertTrue(ObjUtil.isValidIfNumber(Double.MIN_VALUE));
+ Assert.assertFalse(ObjUtil.isValidIfNumber(Float.NEGATIVE_INFINITY));
+ Assert.assertFalse(ObjUtil.isValidIfNumber(Float.NaN));
+ Assert.assertTrue(ObjUtil.isValidIfNumber(Float.MIN_VALUE));
}
+
+ @Test
+ public void compareTest() {
+ Assert.assertEquals(0, ObjUtil.compare(1, 1));
+ Assert.assertEquals(1, ObjUtil.compare(1, null));
+ Assert.assertEquals(-1, ObjUtil.compare(null, 1));
+
+ Assert.assertEquals(-1, ObjUtil.compare(1, null, true));
+ Assert.assertEquals(1, ObjUtil.compare(null, 1, true));
+ }
+
+ @Test
+ public void getTypeArgumentTest() {
+ final Bean bean = new Bean(1);
+ Assert.assertEquals(Integer.class, ObjUtil.getTypeArgument(bean));
+ Assert.assertEquals(String.class, ObjUtil.getTypeArgument(bean, 1));
+ }
+
+ @Test
+ public void toStringTest() {
+ Assert.assertEquals("null", ObjUtil.toString(null));
+ Assert.assertEquals(Collections.emptyMap().toString(), ObjUtil.toString(Collections.emptyMap()));
+ Assert.assertEquals("[1, 2]", Arrays.asList("1", "2").toString());
+ }
+
+ @RequiredArgsConstructor
+ @EqualsAndHashCode
+ private static class ExceptionCloneableBean implements Cloneable {
+ private final Integer id;
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ throw new RuntimeException("can not clone this object");
+ }
+ }
+
+ @RequiredArgsConstructor
+ @EqualsAndHashCode
+ private static class CloneableBean implements Cloneable {
+ private final Integer id;
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+ }
+
+ @RequiredArgsConstructor
+ @EqualsAndHashCode
+ private static class SerializableBean implements Serializable {
+ private final Integer id;
+ }
+
+ @RequiredArgsConstructor
+ @EqualsAndHashCode
+ private static class Bean implements TypeArgument {
+ private final Integer id;
+ }
+
+ private interface TypeArgument {};
+
}