> primitiveTypes = new ArrayList<>(32);
@@ -179,7 +180,7 @@ public class ClassLoaderUtil {
*
*
* @param name 类名
- * @param classLoader {@link ClassLoader},{@code null} 则使用系统默认ClassLoader
+ * @param classLoader {@link ClassLoader},{@code null} 则使用{@link #getClassLoader()}获取
* @param isInitialized 是否初始化类(调用static模块内容和初始化static属性)
* @return 类名对应的类
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
@@ -189,49 +190,18 @@ public class ClassLoaderUtil {
// 自动将包名中的"/"替换为"."
name = name.replace(CharPool.SLASH, CharPool.DOT);
+ if(null == classLoader){
+ classLoader = getClassLoader();
+ }
// 加载原始类型和缓存中的类
Class> clazz = loadPrimitiveClass(name);
if (clazz == null) {
- clazz = CLASS_CACHE.get(name);
+ final String finalName = name;
+ final ClassLoader finalClassLoader = classLoader;
+ clazz = CLASS_CACHE.computeIfAbsent(Pair.of(name, classLoader), (key)-> doLoadClass(finalName, finalClassLoader, isInitialized));
}
- if (clazz != null) {
- return clazz;
- }
-
- if (name.endsWith(ARRAY_SUFFIX)) {
- // 对象数组"java.lang.String[]"风格
- final String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
- final Class> elementClass = loadClass(elementClassName, classLoader, isInitialized);
- clazz = Array.newInstance(elementClass, 0).getClass();
- } else if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
- // "[Ljava.lang.String;" 风格
- final String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
- final Class> elementClass = loadClass(elementName, classLoader, isInitialized);
- clazz = Array.newInstance(elementClass, 0).getClass();
- } else if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
- // "[[I" 或 "[[Ljava.lang.String;" 风格
- final String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
- final Class> elementClass = loadClass(elementName, classLoader, isInitialized);
- clazz = Array.newInstance(elementClass, 0).getClass();
- } else {
- // 加载普通类
- if (null == classLoader) {
- classLoader = getClassLoader();
- }
- try {
- clazz = Class.forName(name, isInitialized, classLoader);
- } catch (ClassNotFoundException ex) {
- // 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
- clazz = tryLoadInnerClass(name, classLoader, isInitialized);
- if (null == clazz) {
- throw new UtilException(ex);
- }
- }
- }
-
- // 加入缓存并返回
- return CLASS_CACHE.put(name, clazz);
+ return clazz;
}
/**
@@ -311,6 +281,47 @@ public class ClassLoaderUtil {
}
// ----------------------------------------------------------------------------------- Private method start
+ /**
+ * 加载非原始类类,无缓存
+ * @param name 类名
+ * @param classLoader {@link ClassLoader}
+ * @param isInitialized 是否初始化
+ * @return 类
+ */
+ private static Class> doLoadClass(String name, ClassLoader classLoader, boolean isInitialized){
+ Class> clazz;
+ if (name.endsWith(ARRAY_SUFFIX)) {
+ // 对象数组"java.lang.String[]"风格
+ final String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
+ final Class> elementClass = loadClass(elementClassName, classLoader, isInitialized);
+ clazz = Array.newInstance(elementClass, 0).getClass();
+ } else if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
+ // "[Ljava.lang.String;" 风格
+ final String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
+ final Class> elementClass = loadClass(elementName, classLoader, isInitialized);
+ clazz = Array.newInstance(elementClass, 0).getClass();
+ } else if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
+ // "[[I" 或 "[[Ljava.lang.String;" 风格
+ final String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
+ final Class> elementClass = loadClass(elementName, classLoader, isInitialized);
+ clazz = Array.newInstance(elementClass, 0).getClass();
+ } else {
+ // 加载普通类
+ if (null == classLoader) {
+ classLoader = getClassLoader();
+ }
+ try {
+ clazz = Class.forName(name, isInitialized, classLoader);
+ } catch (ClassNotFoundException ex) {
+ // 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
+ clazz = tryLoadInnerClass(name, classLoader, isInitialized);
+ if (null == clazz) {
+ throw new UtilException(ex);
+ }
+ }
+ }
+ return clazz;
+ }
/**
* 尝试转换并加载内部类,例如java.lang.Thread.State =》java.lang.Thread$State
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
index a25d41504..e697fed49 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ClassUtil.java
@@ -999,26 +999,44 @@ public class ClassUtil {
* @since 3.0.8
*/
public static Object getDefaultValue(Class> clazz) {
+ // 原始类型
if (clazz.isPrimitive()) {
- if (long.class == clazz) {
- return 0L;
- } else if (int.class == clazz) {
- return 0;
- } else if (short.class == clazz) {
- return (short) 0;
- } else if (char.class == clazz) {
- return (char) 0;
- } else if (byte.class == clazz) {
- return (byte) 0;
- } else if (double.class == clazz) {
- return 0D;
- } else if (float.class == clazz) {
- return 0f;
- } else if (boolean.class == clazz) {
- return false;
- }
+ return getPrimitiveDefaultValue(clazz);
}
+ return null;
+ }
+ /**
+ * 获取指定原始类型分的默认值
+ * 默认值规则为:
+ *
+ *
+ * 1、如果为原始类型,返回0
+ * 2、非原始类型返回{@code null}
+ *
+ *
+ * @param clazz 类
+ * @return 默认值
+ * @since 5.8.0
+ */
+ public static Object getPrimitiveDefaultValue(Class> clazz) {
+ if (long.class == clazz) {
+ return 0L;
+ } else if (int.class == clazz) {
+ return 0;
+ } else if (short.class == clazz) {
+ return (short) 0;
+ } else if (char.class == clazz) {
+ return (char) 0;
+ } else if (byte.class == clazz) {
+ return (byte) 0;
+ } else if (double.class == clazz) {
+ return 0D;
+ } else if (float.class == clazz) {
+ return 0f;
+ } else if (boolean.class == clazz) {
+ return false;
+ }
return null;
}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
index 7c760583f..9e1278ebc 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/IdcardUtil.java
@@ -15,11 +15,11 @@ import java.util.Objects;
/**
* 身份证相关工具类
- * see https://www.oschina.net/code/snippet_1611_2881
+ * see https://www.oschina.net/code/snippet_1611_2881
*
*
* 本工具并没有对行政区划代码做校验,如有需求,请参阅(2018年10月):
- * http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/20181011221630.html
+ * http://www.mca.gov.cn/article/sj/xzqh/2018/201804-12/20181011221630.html
*
*
* @author Looly
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
index 48e179d2a..3deccb27a 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
@@ -2541,7 +2541,7 @@ public class NumberUtil {
/**
* int值转byte数组,使用大端字节序(高位字节在前,低位字节在后)
- * 见:http://www.ruanyifeng.com/blog/2016/11/byte-order.html
+ * 见:http://www.ruanyifeng.com/blog/2016/11/byte-order.html
*
* @param value 值
* @return byte数组
@@ -2560,7 +2560,7 @@ public class NumberUtil {
/**
* byte数组转int,使用大端字节序(高位字节在前,低位字节在后)
- * 见:http://www.ruanyifeng.com/blog/2016/11/byte-order.html
+ * 见:http://www.ruanyifeng.com/blog/2016/11/byte-order.html
*
* @param bytes byte数组
* @return int
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
index 7b746bc6e..39d94196e 100755
--- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java
@@ -8,11 +8,12 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.lang.Filter;
-import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.lang.reflect.MethodHandleUtil;
import cn.hutool.core.map.MapUtil;
+import cn.hutool.core.map.WeakConcurrentMap;
import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -36,15 +37,15 @@ public class ReflectUtil {
/**
* 构造对象缓存
*/
- private static final SimpleCache, Constructor>[]> CONSTRUCTORS_CACHE = new SimpleCache<>();
+ private static final WeakConcurrentMap, Constructor>[]> CONSTRUCTORS_CACHE = new WeakConcurrentMap<>();
/**
* 字段缓存
*/
- private static final SimpleCache, Field[]> FIELDS_CACHE = new SimpleCache<>();
+ private static final WeakConcurrentMap, Field[]> FIELDS_CACHE = new WeakConcurrentMap<>();
/**
* 方法缓存
*/
- private static final SimpleCache, Method[]> METHODS_CACHE = new SimpleCache<>();
+ private static final WeakConcurrentMap, Method[]> METHODS_CACHE = new WeakConcurrentMap<>();
// --------------------------------------------------------------------------------------------------------- Constructor
@@ -86,7 +87,7 @@ public class ReflectUtil {
@SuppressWarnings("unchecked")
public static Constructor[] getConstructors(Class beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return (Constructor[]) CONSTRUCTORS_CACHE.get(beanClass, () -> getConstructorsDirectly(beanClass));
+ return (Constructor[]) CONSTRUCTORS_CACHE.computeIfAbsent(beanClass, () -> getConstructorsDirectly(beanClass));
}
/**
@@ -175,7 +176,7 @@ public class ReflectUtil {
*/
public static Field[] getFields(Class> beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return FIELDS_CACHE.get(beanClass, () -> getFieldsDirectly(beanClass, true));
+ return FIELDS_CACHE.computeIfAbsent(beanClass, () -> getFieldsDirectly(beanClass, true));
}
@@ -651,7 +652,7 @@ public class ReflectUtil {
*/
public static Method[] getMethods(Class> beanClass) throws SecurityException {
Assert.notNull(beanClass);
- return METHODS_CACHE.get(beanClass,
+ return METHODS_CACHE.computeIfAbsent(beanClass,
() -> getMethodsDirectly(beanClass, true, true));
}
@@ -864,30 +865,45 @@ public class ReflectUtil {
*
*
* @param 对象类型
- * @param beanClass 被构造的类
+ * @param type 被构造的类
* @return 构造后的对象,构造失败返回{@code null}
*/
@SuppressWarnings("unchecked")
- public static T newInstanceIfPossible(Class beanClass) {
- Assert.notNull(beanClass);
+ public static T newInstanceIfPossible(Class type) {
+ Assert.notNull(type);
+
+ // 原始类型
+ if(type.isPrimitive()){
+ return (T) ClassUtil.getPrimitiveDefaultValue(type);
+ }
// 某些特殊接口的实例化按照默认实现进行
- if (beanClass.isAssignableFrom(AbstractMap.class)) {
- beanClass = (Class) HashMap.class;
- } else if (beanClass.isAssignableFrom(List.class)) {
- beanClass = (Class) ArrayList.class;
- } else if (beanClass.isAssignableFrom(Set.class)) {
- beanClass = (Class) HashSet.class;
+ if (type.isAssignableFrom(AbstractMap.class)) {
+ type = (Class) HashMap.class;
+ } else if (type.isAssignableFrom(List.class)) {
+ type = (Class) ArrayList.class;
+ } else if (type.isAssignableFrom(Set.class)) {
+ type = (Class) HashSet.class;
}
try {
- return newInstance(beanClass);
+ return newInstance(type);
} catch (Exception e) {
// ignore
// 默认构造不存在的情况下查找其它构造
}
- final Constructor[] constructors = getConstructors(beanClass);
+ // 枚举
+ if (type.isEnum()) {
+ return type.getEnumConstants()[0];
+ }
+
+ // 数组
+ if (type.isArray()) {
+ return (T) Array.newInstance(type.getComponentType(), 0);
+ }
+
+ final Constructor[] constructors = getConstructors(type);
Class>[] parameterTypes;
for (Constructor constructor : constructors) {
parameterTypes = constructor.getParameterTypes();
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationForTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationForTest.java
index 83210ae90..f109e836d 100755
--- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationForTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationForTest.java
@@ -7,7 +7,7 @@ import java.lang.annotation.Target;
/**
* 用于单元测试的注解类
- * 注解类相关说明见:https://www.cnblogs.com/xdp-gacl/p/3622275.html
+ * 注解类相关说明见:https://www.cnblogs.com/xdp-gacl/p/3622275.html
*
* @author looly
*/
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
index 3340dcf37..167b62d2c 100755
--- a/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/AnnotationUtilTest.java
@@ -3,8 +3,25 @@ package cn.hutool.core.annotation;
import org.junit.Assert;
import org.junit.Test;
+import java.lang.annotation.Annotation;
+
public class AnnotationUtilTest {
+ @Test
+ public void getCombinationAnnotationsTest(){
+ Annotation[] annotations = AnnotationUtil.getAnnotations(ClassWithAnnotation.class, true);
+ Assert.assertNotNull(annotations);
+ Assert.assertEquals(3, annotations.length);
+ }
+
+ @Test
+ public void getCombinationAnnotationsWithClassTest(){
+ AnnotationForTest[] annotations = AnnotationUtil.getCombinationAnnotations(ClassWithAnnotation.class, AnnotationForTest.class);
+ Assert.assertNotNull(annotations);
+ Assert.assertEquals(2, annotations.length);
+ Assert.assertEquals("测试", annotations[0].value());
+ }
+
@Test
public void getAnnotationValueTest() {
Object value = AnnotationUtil.getAnnotationValue(ClassWithAnnotation.class, AnnotationForTest.class);
@@ -23,6 +40,7 @@ public class AnnotationUtilTest {
}
@AnnotationForTest("测试")
+ @RepeatAnnotationForTest
static class ClassWithAnnotation{
public void test(){
diff --git a/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java
new file mode 100755
index 000000000..cc71c68da
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/annotation/RepeatAnnotationForTest.java
@@ -0,0 +1,16 @@
+package cn.hutool.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author hongda.li 2022-04-26 17:09
+ */
+@AnnotationForTest("repeat-annotation")
+@Retention(RetentionPolicy.RUNTIME)
+// Target注解决定MyAnnotation注解可以加在哪些成分上,如加在类身上,或者属性身上,或者方法身上等成分
+@Target({ ElementType.METHOD, ElementType.TYPE })
+public @interface RepeatAnnotationForTest {
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java
index 6e9a687b7..89de82f85 100755
--- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java
@@ -777,4 +777,20 @@ public class BeanUtilTest {
public static class Test2 {
private List strList;
}
+
+ @Test
+ public void issuesI53O9JTest(){
+ Map map = new HashMap<>();
+ map.put("statusIdUpdateTime", "");
+
+ WkCrmCustomer customer = new WkCrmCustomer();
+ BeanUtil.copyProperties(map, customer);
+
+ Assert.assertNull(customer.getStatusIdUpdateTime());
+ }
+
+ @Data
+ public static class WkCrmCustomer{
+ private LocalDateTime statusIdUpdateTime;
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/codec/HashidsTest.java b/hutool-core/src/test/java/cn/hutool/core/codec/HashidsTest.java
new file mode 100755
index 000000000..458cde5b1
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/codec/HashidsTest.java
@@ -0,0 +1,20 @@
+package cn.hutool.core.codec;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HashidsTest {
+ @Test
+ public void hexEncodeDecode() {
+ final Hashids hashids = Hashids.create("my awesome salt".toCharArray());
+ final String encoded1 = hashids.encodeFromHex("507f1f77bcf86cd799439011");
+ final String encoded2 = hashids.encodeFromHex("0x507f1f77bcf86cd799439011");
+ final String encoded3 = hashids.encodeFromHex("0X507f1f77bcf86cd799439011");
+
+ Assert.assertEquals("R2qnd2vkOJTXm7XV7yq4", encoded1);
+ Assert.assertEquals(encoded1, encoded2);
+ Assert.assertEquals(encoded1, encoded3);
+ final String decoded = hashids.decodeToHex(encoded1);
+ Assert.assertEquals("507f1f77bcf86cd799439011", decoded);
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java
index ad0582e18..512b13e2d 100755
--- a/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/collection/CollUtilTest.java
@@ -878,6 +878,36 @@ public class CollUtilTest {
Assert.assertEquals(people.get(1).getGender(), "小孩");
}
+ @Test
+ public void distinctTest(){
+ final ArrayList distinct = CollUtil.distinct(ListUtil.of(5, 3, 10, 9, 0, 5, 10, 9));
+ Assert.assertEquals(ListUtil.of(5, 3, 10, 9, 0), distinct);
+ }
+
+ @Test
+ public void distinctByFunctionTest(){
+ List people = Arrays.asList(
+ new Person("aa", 12, "man", 1),
+ new Person("bb", 13, "woman", 2),
+ new Person("cc", 14, "man", 3),
+ new Person("dd", 15, "woman", 4),
+ new Person("ee", 16, "woman", 5),
+ new Person("ff", 17, "man", 6)
+ );
+
+ // 覆盖模式下ff覆盖了aa,ee覆盖了bb
+ List distinct = CollUtil.distinct(people, Person::getGender, true);
+ Assert.assertEquals(2, distinct.size());
+ Assert.assertEquals("ff", distinct.get(0).getName());
+ Assert.assertEquals("ee", distinct.get(1).getName());
+
+ // 非覆盖模式下,保留了最早加入的aa和bb
+ distinct = CollUtil.distinct(people, Person::getGender, false);
+ Assert.assertEquals(2, distinct.size());
+ Assert.assertEquals("aa", distinct.get(0).getName());
+ Assert.assertEquals("bb", distinct.get(1).getName());
+ }
+
@Data
@AllArgsConstructor
static class Person {
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
index b9de72b6f..7874b5cd9 100755
--- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
@@ -1029,6 +1029,7 @@ public class DateUtilTest {
}
@Test
+ @SuppressWarnings("ConstantConditions")
public void isOverlapTest() {
DateTime oneStartTime = DateUtil.parse("2022-01-01 10:10:10");
DateTime oneEndTime = DateUtil.parse("2022-01-01 11:10:10");
@@ -1055,6 +1056,16 @@ public class DateUtilTest {
Assert.assertFalse(DateUtil.isOverlap(realStartTime1,realEndTime1,startTime,endTime));
Assert.assertFalse(DateUtil.isOverlap(startTime,endTime,realStartTime1,realEndTime1));
+ }
+ @Test
+ public void isInTest(){
+ String sourceStr = "2022-04-19 00:00:00";
+ String startTimeStr = "2022-04-19 00:00:00";
+ String endTimeStr = "2022-04-19 23:59:59";
+ boolean between = DateUtil.isIn(DateUtil.parse(startTimeStr),
+ DateUtil.parse(endTimeStr),
+ DateUtil.parse(sourceStr));
+ Assert.assertTrue(between);
}
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
index b4c85a1aa..4ea9bddb6 100755
--- a/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/io/FileTypeUtilTest.java
@@ -5,7 +5,9 @@ import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
+import java.io.BufferedInputStream;
import java.io.File;
+import java.io.IOException;
/**
* 文件类型判断单元测试
@@ -62,4 +64,15 @@ public class FileTypeUtilTest {
Assert.assertEquals("xlsx", type);
}
+ @Test
+ @Ignore
+ public void getTypeFromInputStream() throws IOException {
+ File file = FileUtil.file("d:/test/pic.jpg");
+ final BufferedInputStream inputStream = FileUtil.getInputStream(file);
+ inputStream.mark(0);
+ String type = FileTypeUtil.getType(inputStream);
+
+ inputStream.reset();
+ }
+
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTest.java
index ee667974b..01a92e70f 100755
--- a/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTest.java
@@ -75,4 +75,9 @@ public class ConsoleTest {
}
}
+ @Test
+ public void printColorTest(){
+ System.out.print("\33[30;1m A \u001b[31;2m B \u001b[32;1m C \u001b[33;1m D \u001b[0m");
+ }
+
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/SimpleCacheTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/SimpleCacheTest.java
index e32c78a90..8b15d28e6 100755
--- a/hutool-core/src/test/java/cn/hutool/core/lang/SimpleCacheTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/SimpleCacheTest.java
@@ -50,7 +50,7 @@ public class SimpleCacheTest {
final SimpleCache cache = new SimpleCache<>();
final ConcurrencyTester tester = new ConcurrencyTester(9000);
tester.test(()-> cache.get("aaa", ()-> {
- ThreadUtil.sleep(1000);
+ ThreadUtil.sleep(200);
return "aaaValue";
}));
diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ansi/AnsiEncoderTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ansi/AnsiEncoderTest.java
new file mode 100755
index 000000000..710c5c0f0
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/ansi/AnsiEncoderTest.java
@@ -0,0 +1,13 @@
+package cn.hutool.core.lang.ansi;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AnsiEncoderTest {
+
+ @Test
+ public void encodeTest(){
+ final String encode = AnsiEncoder.encode(AnsiColor.GREEN, "Hutool test");
+ Assert.assertEquals("\u001B[32mHutool test\u001B[0;39m", encode);
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/map/FuncMapTest.java b/hutool-core/src/test/java/cn/hutool/core/map/FuncMapTest.java
new file mode 100755
index 000000000..1a26d127a
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/map/FuncMapTest.java
@@ -0,0 +1,22 @@
+package cn.hutool.core.map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.HashMap;
+
+public class FuncMapTest {
+
+ @Test
+ public void putGetTest(){
+ final FuncMap