diff --git a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java index c9a7070cc..124ac5eac 100755 --- a/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/annotation/AnnotationUtil.java @@ -299,7 +299,7 @@ public class AnnotationUtil { * * @param annotationType 注解类型 * @return 注解属性 - * @see 6.0.0 + * @since 6.0.0 */ public static Method[] getAnnotationAttributes(final Class annotationType) { // TODO 改为通过带缓存的反射工具类完成 @@ -325,7 +325,7 @@ public class AnnotationUtil { * * @param attribute 方法对象 * @return 是否 - * @see 6.0.0 + * @since 6.0.0 */ public static boolean isAnnotationAttribute(final Method attribute) { return !MethodUtil.isEqualsMethod(attribute) diff --git a/hutool-core/src/main/java/cn/hutool/core/classloader/ClassLoaderUtil.java b/hutool-core/src/main/java/cn/hutool/core/classloader/ClassLoaderUtil.java index 8ed22b45d..bc0240fa6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/classloader/ClassLoaderUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/classloader/ClassLoaderUtil.java @@ -55,7 +55,7 @@ public class ClassLoaderUtil { static { final List> primitiveTypes = new ArrayList<>(32); // 加入原始类型 - primitiveTypes.addAll(BasicType.PRIMITIVE_WRAPPER_MAP.keySet()); + primitiveTypes.addAll(BasicType.getPrimitiveSet()); // 加入原始类型数组类型 primitiveTypes.add(boolean[].class); primitiveTypes.add(byte[].class); diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java index bb90147d4..b67cda84f 100755 --- a/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/CollUtil.java @@ -2163,7 +2163,7 @@ public class CollUtil { * @return 只读集合 * @since 5.2.6 */ - public static Collection unmodifiable(final Collection c) { + public static Collection view(final Collection c) { if (null == c) { return null; } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/BasicType.java b/hutool-core/src/main/java/cn/hutool/core/convert/BasicType.java index 6870bc8b8..bd484cfdf 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/BasicType.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/BasicType.java @@ -1,22 +1,23 @@ package cn.hutool.core.convert; -import cn.hutool.core.map.SafeConcurrentHashMap; +import cn.hutool.core.map.BiMap; -import java.util.Map; +import java.util.HashMap; +import java.util.Set; /** * 基本变量类型的枚举
* 基本类型枚举包括原始类型和包装类型 + * * @author xiaoleilu */ public enum BasicType { BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING; - /** 包装类型为Key,原始类型为Value,例如: Integer.class =》 int.class. */ - public static final Map, Class> WRAPPER_PRIMITIVE_MAP = new SafeConcurrentHashMap<>(8); - /** 原始类型为Key,包装类型为Value,例如: int.class =》 Integer.class. */ - public static final Map, Class> PRIMITIVE_WRAPPER_MAP = new SafeConcurrentHashMap<>(8); - + /** + * 包装类型为Key,原始类型为Value,例如: Integer.class =》 int.class. + */ + private static final BiMap, Class> WRAPPER_PRIMITIVE_MAP = new BiMap<>(new HashMap<>(8, 1)); static { WRAPPER_PRIMITIVE_MAP.put(Boolean.class, boolean.class); WRAPPER_PRIMITIVE_MAP.put(Byte.class, byte.class); @@ -26,35 +27,75 @@ public enum BasicType { WRAPPER_PRIMITIVE_MAP.put(Integer.class, int.class); WRAPPER_PRIMITIVE_MAP.put(Long.class, long.class); WRAPPER_PRIMITIVE_MAP.put(Short.class, short.class); - - for (final Map.Entry, Class> entry : WRAPPER_PRIMITIVE_MAP.entrySet()) { - PRIMITIVE_WRAPPER_MAP.put(entry.getValue(), entry.getKey()); - } } /** * 原始类转为包装类,非原始类返回原类 + * * @param clazz 原始类 * @return 包装类 */ - public static Class wrap(final Class clazz){ - if(null == clazz || false == clazz.isPrimitive()){ + public static Class wrap(final Class clazz) { + return wrap(clazz, false); + } + + /** + * 原始类转为包装类,非原始类返回原类 + * + * @param clazz 原始类 + * @param errorReturnNull 如果没有对应类的原始类型,是否返回{@code null},{@code true}返回{@code null},否则返回原class + * @return 包装类 + */ + public static Class wrap(final Class clazz, boolean errorReturnNull) { + if (null == clazz || false == clazz.isPrimitive()) { return clazz; } - final Class result = PRIMITIVE_WRAPPER_MAP.get(clazz); - return (null == result) ? clazz : result; + final Class result = WRAPPER_PRIMITIVE_MAP.getInverse().get(clazz); + return (null == result) ? errorReturnNull ? null : clazz : result; } /** * 包装类转为原始类,非包装类返回原类 + * * @param clazz 包装类 * @return 原始类 */ - public static Class unWrap(final Class clazz){ - if(null == clazz || clazz.isPrimitive()){ + public static Class unWrap(final Class clazz) { + if (null == clazz || clazz.isPrimitive()) { return clazz; } final Class result = WRAPPER_PRIMITIVE_MAP.get(clazz); return (null == result) ? clazz : result; } + + /** + * 是否为包装类型 + * + * @param clazz 类 + * @return 是否为包装类型 + */ + public static boolean isPrimitiveWrapper(final Class clazz) { + if (null == clazz) { + return false; + } + return WRAPPER_PRIMITIVE_MAP.containsKey(clazz); + } + + /** + * 获取所有原始类型 + * + * @return 所有原始类型 + */ + public static Set> getPrimitiveSet() { + return WRAPPER_PRIMITIVE_MAP.getInverse().keySet(); + } + + /** + * 获取所有原始类型 + * + * @return 所有原始类型 + */ + public static Set> getWrapperSet() { + return WRAPPER_PRIMITIVE_MAP.keySet(); + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java index 9a8886b3a..ed058bf66 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/MapUtil.java @@ -195,42 +195,42 @@ public class MapUtil extends MapGetUtil { } /** - * 新建一个初始容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} 的ConcurrentHashMap + * 新建一个初始容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} 的{@link SafeConcurrentHashMap} * * @param key的类型 * @param value的类型 - * @return ConcurrentHashMap + * @return {@link SafeConcurrentHashMap} */ - public static ConcurrentHashMap newConcurrentHashMap() { - return new ConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); + public static ConcurrentHashMap newSafeConcurrentHashMap() { + return new SafeConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); } /** - * 新建一个ConcurrentHashMap + * 新建一个{@link SafeConcurrentHashMap} * * @param size 初始容量,当传入的容量小于等于0时,容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} * @param key的类型 * @param value的类型 - * @return ConcurrentHashMap + * @return {@link SafeConcurrentHashMap} */ - public static ConcurrentHashMap newConcurrentHashMap(final int size) { + public static ConcurrentHashMap newSafeConcurrentHashMap(final int size) { final int initCapacity = size <= 0 ? DEFAULT_INITIAL_CAPACITY : size; - return new ConcurrentHashMap<>(initCapacity); + return new SafeConcurrentHashMap<>(initCapacity); } /** - * 传入一个Map将其转化为ConcurrentHashMap类型 + * 传入一个Map将其转化为{@link SafeConcurrentHashMap}类型 * * @param map map * @param key的类型 * @param value的类型 - * @return ConcurrentHashMap + * @return {@link SafeConcurrentHashMap} */ - public static ConcurrentHashMap newConcurrentHashMap(final Map map) { + public static ConcurrentHashMap newSafeConcurrentHashMap(final Map map) { if (isEmpty(map)) { return new ConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); } - return new ConcurrentHashMap<>(map); + return new SafeConcurrentHashMap<>(map); } /** @@ -888,7 +888,7 @@ public class MapUtil extends MapGetUtil { * @return 不修改Map * @since 5.2.6 */ - public static Map unmodifiable(final Map map) { + public static Map view(final Map map) { return Collections.unmodifiableMap(map); } @@ -1270,6 +1270,11 @@ public class MapUtil extends MapGetUtil { * A temporary workaround for Java 8 specific performance issue JDK-8161372 .
* This class should be removed once we drop Java 8 support. * + * @param 键类型 + * @param 值类型 + * @param map Map,一般用于线程安全的Map + * @param key 键 + * @param mappingFunction 值计算函数 * @see https://bugs.openjdk.java.net/browse/JDK-8161372 */ public static V computeIfAbsent(final Map map, final K key, final Function mappingFunction) { diff --git a/hutool-core/src/main/java/cn/hutool/core/net/url/UrlQuery.java b/hutool-core/src/main/java/cn/hutool/core/net/url/UrlQuery.java index c5f8bd951..54a0a0742 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/url/UrlQuery.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/url/UrlQuery.java @@ -206,7 +206,7 @@ public class UrlQuery { * @return 查询的Map,只读 */ public Map getQueryMap() { - return MapUtil.unmodifiable(this.query); + return MapUtil.view(this.query); } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java b/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java index bf21785b4..7191fc777 100644 --- a/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/reflect/ClassUtil.java @@ -363,10 +363,7 @@ public class ClassUtil { * @return 是否为包装类型 */ public static boolean isPrimitiveWrapper(final Class clazz) { - if (null == clazz) { - return false; - } - return BasicType.WRAPPER_PRIMITIVE_MAP.containsKey(clazz); + return BasicType.isPrimitiveWrapper(clazz); } /** @@ -450,12 +447,11 @@ public class ClassUtil { // 基本类型 if (targetType.isPrimitive()) { - // 原始类型 - final Class resolvedPrimitive = BasicType.WRAPPER_PRIMITIVE_MAP.get(sourceType); - return targetType.equals(resolvedPrimitive); + // 目标为原始类型 + return targetType.equals(BasicType.unWrap(sourceType)); } else { - // 包装类型 - final Class resolvedWrapper = BasicType.PRIMITIVE_WRAPPER_MAP.get(sourceType); + // 目标为包装类型 + final Class resolvedWrapper = BasicType.wrap(sourceType, true); return resolvedWrapper != null && targetType.isAssignableFrom(resolvedWrapper); } } diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/BasicTypeTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/BasicTypeTest.java new file mode 100644 index 000000000..778174172 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/convert/BasicTypeTest.java @@ -0,0 +1,33 @@ +package cn.hutool.core.convert; + +import org.junit.Assert; +import org.junit.Test; + +public class BasicTypeTest { + + @Test + public void wrapTest(){ + Assert.assertEquals(Integer.class, BasicType.wrap(int.class)); + Assert.assertEquals(Integer.class, BasicType.wrap(Integer.class)); + Assert.assertEquals(String.class, BasicType.wrap(String.class)); + Assert.assertNull(BasicType.wrap(null)); + } + + @Test + public void unWrapTest(){ + Assert.assertEquals(int.class, BasicType.unWrap(int.class)); + Assert.assertEquals(int.class, BasicType.unWrap(Integer.class)); + Assert.assertEquals(String.class, BasicType.unWrap(String.class)); + Assert.assertNull(BasicType.unWrap(null)); + } + + @Test + public void getPrimitiveSetTest(){ + Assert.assertEquals(8, BasicType.getPrimitiveSet().size()); + } + + @Test + public void getWrapperSetTest(){ + Assert.assertEquals(8, BasicType.getWrapperSet().size()); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ClassUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ClassUtilTest.java index 9532641a9..151b4fc74 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/ClassUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ClassUtilTest.java @@ -41,4 +41,11 @@ public class ClassUtilTest { final String classDir = ClassUtil.getLocationPath(ClassUtilTest.class); Assert.assertTrue(Objects.requireNonNull(classDir).endsWith("/hutool-core/target/test-classes/")); } + + @Test + public void isAssignableTest(){ + Assert.assertTrue(ClassUtil.isAssignable(int.class, int.class)); + Assert.assertTrue(ClassUtil.isAssignable(int.class, Integer.class)); + Assert.assertFalse(ClassUtil.isAssignable(int.class, String.class)); + } } diff --git a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java index 155d2c301..d31f9ab0f 100644 --- a/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java +++ b/hutool-http/src/main/java/cn/hutool/http/server/HttpServerRequest.java @@ -219,7 +219,7 @@ public class HttpServerRequest extends HttpServerBase { */ public Map getCookieMap() { if (null == this.cookieCache) { - cookieCache = MapUtil.unmodifiable(MapUtil.putAll( + cookieCache = MapUtil.view(MapUtil.putAll( new CaseInsensitiveMap<>(), NetUtil.parseCookies(getCookiesStr()), HttpCookie::getName));