This commit is contained in:
Looly 2022-09-15 11:20:54 +08:00
parent 3b5ba16c93
commit 08a829cf6d
10 changed files with 127 additions and 45 deletions

View File

@ -299,7 +299,7 @@ public class AnnotationUtil {
* *
* @param annotationType 注解类型 * @param annotationType 注解类型
* @return 注解属性 * @return 注解属性
* @see 6.0.0 * @since 6.0.0
*/ */
public static Method[] getAnnotationAttributes(final Class<? extends Annotation> annotationType) { public static Method[] getAnnotationAttributes(final Class<? extends Annotation> annotationType) {
// TODO 改为通过带缓存的反射工具类完成 // TODO 改为通过带缓存的反射工具类完成
@ -325,7 +325,7 @@ public class AnnotationUtil {
* *
* @param attribute 方法对象 * @param attribute 方法对象
* @return 是否 * @return 是否
* @see 6.0.0 * @since 6.0.0
*/ */
public static boolean isAnnotationAttribute(final Method attribute) { public static boolean isAnnotationAttribute(final Method attribute) {
return !MethodUtil.isEqualsMethod(attribute) return !MethodUtil.isEqualsMethod(attribute)

View File

@ -55,7 +55,7 @@ public class ClassLoaderUtil {
static { static {
final List<Class<?>> primitiveTypes = new ArrayList<>(32); final List<Class<?>> primitiveTypes = new ArrayList<>(32);
// 加入原始类型 // 加入原始类型
primitiveTypes.addAll(BasicType.PRIMITIVE_WRAPPER_MAP.keySet()); primitiveTypes.addAll(BasicType.getPrimitiveSet());
// 加入原始类型数组类型 // 加入原始类型数组类型
primitiveTypes.add(boolean[].class); primitiveTypes.add(boolean[].class);
primitiveTypes.add(byte[].class); primitiveTypes.add(byte[].class);

View File

@ -2163,7 +2163,7 @@ public class CollUtil {
* @return 只读集合 * @return 只读集合
* @since 5.2.6 * @since 5.2.6
*/ */
public static <T> Collection<T> unmodifiable(final Collection<? extends T> c) { public static <T> Collection<T> view(final Collection<? extends T> c) {
if (null == c) { if (null == c) {
return null; return null;
} }

View File

@ -1,22 +1,23 @@
package cn.hutool.core.convert; 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;
/** /**
* 基本变量类型的枚举<br> * 基本变量类型的枚举<br>
* 基本类型枚举包括原始类型和包装类型 * 基本类型枚举包括原始类型和包装类型
*
* @author xiaoleilu * @author xiaoleilu
*/ */
public enum BasicType { public enum BasicType {
BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING; BYTE, SHORT, INT, INTEGER, LONG, DOUBLE, FLOAT, BOOLEAN, CHAR, CHARACTER, STRING;
/** 包装类型为Key原始类型为Value例如 Integer.class =》 int.class. */ /**
public static final Map<Class<?>, Class<?>> WRAPPER_PRIMITIVE_MAP = new SafeConcurrentHashMap<>(8); * 包装类型为Key原始类型为Value例如 Integer.class = int.class.
/** 原始类型为Key包装类型为Value例如 int.class =》 Integer.class. */ */
public static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_MAP = new SafeConcurrentHashMap<>(8); private static final BiMap<Class<?>, Class<?>> WRAPPER_PRIMITIVE_MAP = new BiMap<>(new HashMap<>(8, 1));
static { static {
WRAPPER_PRIMITIVE_MAP.put(Boolean.class, boolean.class); WRAPPER_PRIMITIVE_MAP.put(Boolean.class, boolean.class);
WRAPPER_PRIMITIVE_MAP.put(Byte.class, byte.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(Integer.class, int.class);
WRAPPER_PRIMITIVE_MAP.put(Long.class, long.class); WRAPPER_PRIMITIVE_MAP.put(Long.class, long.class);
WRAPPER_PRIMITIVE_MAP.put(Short.class, short.class); WRAPPER_PRIMITIVE_MAP.put(Short.class, short.class);
for (final Map.Entry<Class<?>, Class<?>> entry : WRAPPER_PRIMITIVE_MAP.entrySet()) {
PRIMITIVE_WRAPPER_MAP.put(entry.getValue(), entry.getKey());
}
} }
/** /**
* 原始类转为包装类非原始类返回原类 * 原始类转为包装类非原始类返回原类
*
* @param clazz 原始类 * @param clazz 原始类
* @return 包装类 * @return 包装类
*/ */
public static Class<?> wrap(final Class<?> clazz){ public static Class<?> wrap(final Class<?> clazz) {
if(null == clazz || false == clazz.isPrimitive()){ 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; return clazz;
} }
final Class<?> result = PRIMITIVE_WRAPPER_MAP.get(clazz); final Class<?> result = WRAPPER_PRIMITIVE_MAP.getInverse().get(clazz);
return (null == result) ? clazz : result; return (null == result) ? errorReturnNull ? null : clazz : result;
} }
/** /**
* 包装类转为原始类非包装类返回原类 * 包装类转为原始类非包装类返回原类
*
* @param clazz 包装类 * @param clazz 包装类
* @return 原始类 * @return 原始类
*/ */
public static Class<?> unWrap(final Class<?> clazz){ public static Class<?> unWrap(final Class<?> clazz) {
if(null == clazz || clazz.isPrimitive()){ if (null == clazz || clazz.isPrimitive()) {
return clazz; return clazz;
} }
final Class<?> result = WRAPPER_PRIMITIVE_MAP.get(clazz); final Class<?> result = WRAPPER_PRIMITIVE_MAP.get(clazz);
return (null == result) ? clazz : result; 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<Class<?>> getPrimitiveSet() {
return WRAPPER_PRIMITIVE_MAP.getInverse().keySet();
}
/**
* 获取所有原始类型
*
* @return 所有原始类型
*/
public static Set<Class<?>> getWrapperSet() {
return WRAPPER_PRIMITIVE_MAP.keySet();
}
} }

View File

@ -195,42 +195,42 @@ public class MapUtil extends MapGetUtil {
} }
/** /**
* 新建一个初始容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} ConcurrentHashMap * 新建一个初始容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} {@link SafeConcurrentHashMap}
* *
* @param <K> key的类型 * @param <K> key的类型
* @param <V> value的类型 * @param <V> value的类型
* @return ConcurrentHashMap * @return {@link SafeConcurrentHashMap}
*/ */
public static <K, V> ConcurrentHashMap<K, V> newConcurrentHashMap() { public static <K, V> ConcurrentHashMap<K, V> newSafeConcurrentHashMap() {
return new ConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); return new SafeConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY);
} }
/** /**
* 新建一个ConcurrentHashMap * 新建一个{@link SafeConcurrentHashMap}
* *
* @param size 初始容量当传入的容量小于等于0时容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY} * @param size 初始容量当传入的容量小于等于0时容量为{@link MapUtil#DEFAULT_INITIAL_CAPACITY}
* @param <K> key的类型 * @param <K> key的类型
* @param <V> value的类型 * @param <V> value的类型
* @return ConcurrentHashMap * @return {@link SafeConcurrentHashMap}
*/ */
public static <K, V> ConcurrentHashMap<K, V> newConcurrentHashMap(final int size) { public static <K, V> ConcurrentHashMap<K, V> newSafeConcurrentHashMap(final int size) {
final int initCapacity = size <= 0 ? DEFAULT_INITIAL_CAPACITY : 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 map map
* @param <K> key的类型 * @param <K> key的类型
* @param <V> value的类型 * @param <V> value的类型
* @return ConcurrentHashMap * @return {@link SafeConcurrentHashMap}
*/ */
public static <K, V> ConcurrentHashMap<K, V> newConcurrentHashMap(final Map<K, V> map) { public static <K, V> ConcurrentHashMap<K, V> newSafeConcurrentHashMap(final Map<K, V> map) {
if (isEmpty(map)) { if (isEmpty(map)) {
return new ConcurrentHashMap<>(DEFAULT_INITIAL_CAPACITY); 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 * @return 不修改Map
* @since 5.2.6 * @since 5.2.6
*/ */
public static <K, V> Map<K, V> unmodifiable(final Map<K, V> map) { public static <K, V> Map<K, V> view(final Map<K, V> map) {
return Collections.unmodifiableMap(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 .<br> * A temporary workaround for Java 8 specific performance issue JDK-8161372 .<br>
* This class should be removed once we drop Java 8 support. * This class should be removed once we drop Java 8 support.
* *
* @param <K> 键类型
* @param <V> 值类型
* @param map Map一般用于线程安全的Map
* @param key
* @param mappingFunction 值计算函数
* @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a> * @see <a href="https://bugs.openjdk.java.net/browse/JDK-8161372">https://bugs.openjdk.java.net/browse/JDK-8161372</a>
*/ */
public static <K, V> V computeIfAbsent(final Map<K, V> map, final K key, final Function<? super K, ? extends V> mappingFunction) { public static <K, V> V computeIfAbsent(final Map<K, V> map, final K key, final Function<? super K, ? extends V> mappingFunction) {

View File

@ -206,7 +206,7 @@ public class UrlQuery {
* @return 查询的Map只读 * @return 查询的Map只读
*/ */
public Map<CharSequence, CharSequence> getQueryMap() { public Map<CharSequence, CharSequence> getQueryMap() {
return MapUtil.unmodifiable(this.query); return MapUtil.view(this.query);
} }
/** /**

View File

@ -363,10 +363,7 @@ public class ClassUtil {
* @return 是否为包装类型 * @return 是否为包装类型
*/ */
public static boolean isPrimitiveWrapper(final Class<?> clazz) { public static boolean isPrimitiveWrapper(final Class<?> clazz) {
if (null == clazz) { return BasicType.isPrimitiveWrapper(clazz);
return false;
}
return BasicType.WRAPPER_PRIMITIVE_MAP.containsKey(clazz);
} }
/** /**
@ -450,12 +447,11 @@ public class ClassUtil {
// 基本类型 // 基本类型
if (targetType.isPrimitive()) { if (targetType.isPrimitive()) {
// 原始类型 // 目标为原始类型
final Class<?> resolvedPrimitive = BasicType.WRAPPER_PRIMITIVE_MAP.get(sourceType); return targetType.equals(BasicType.unWrap(sourceType));
return targetType.equals(resolvedPrimitive);
} else { } else {
// 包装类型 // 目标为包装类型
final Class<?> resolvedWrapper = BasicType.PRIMITIVE_WRAPPER_MAP.get(sourceType); final Class<?> resolvedWrapper = BasicType.wrap(sourceType, true);
return resolvedWrapper != null && targetType.isAssignableFrom(resolvedWrapper); return resolvedWrapper != null && targetType.isAssignableFrom(resolvedWrapper);
} }
} }

View File

@ -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());
}
}

View File

@ -41,4 +41,11 @@ public class ClassUtilTest {
final String classDir = ClassUtil.getLocationPath(ClassUtilTest.class); final String classDir = ClassUtil.getLocationPath(ClassUtilTest.class);
Assert.assertTrue(Objects.requireNonNull(classDir).endsWith("/hutool-core/target/test-classes/")); 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));
}
} }

View File

@ -219,7 +219,7 @@ public class HttpServerRequest extends HttpServerBase {
*/ */
public Map<String, HttpCookie> getCookieMap() { public Map<String, HttpCookie> getCookieMap() {
if (null == this.cookieCache) { if (null == this.cookieCache) {
cookieCache = MapUtil.unmodifiable(MapUtil.putAll( cookieCache = MapUtil.view(MapUtil.putAll(
new CaseInsensitiveMap<>(), new CaseInsensitiveMap<>(),
NetUtil.parseCookies(getCookiesStr()), NetUtil.parseCookies(getCookiesStr()),
HttpCookie::getName)); HttpCookie::getName));