diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java index 3d017a647..a79415213 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/CompositeConverter.java @@ -98,20 +98,22 @@ public class CompositeConverter extends RegisterConverter { */ @SuppressWarnings("unchecked") public T convert(Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException { - if (TypeUtil.isUnknown(type) && null == defaultValue) { - // 对于用户不指定目标类型的情况,返回原值 - return (T) value; - } if (ObjUtil.isNull(value)) { return defaultValue; } if (TypeUtil.isUnknown(type)) { + // 对于用户不指定目标类型的情况,返回原值 if(null == defaultValue){ - throw new ConvertException("Unsupported convert to unKnow type: {}", type); + return (T) value; } type = defaultValue.getClass(); } + // value本身实现了Converter接口,直接调用 + if(value instanceof Converter){ + return ((Converter) value).convert(type, value, defaultValue); + } + if (type instanceof TypeReference) { type = ((TypeReference) type).getType(); } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/RegisterConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/RegisterConverter.java index d1426bc9e..7ff40594a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/RegisterConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/RegisterConverter.java @@ -29,9 +29,6 @@ import cn.hutool.core.convert.impl.XMLGregorianCalendarConverter; import cn.hutool.core.convert.impl.ZoneIdConverter; import cn.hutool.core.date.DateTime; import cn.hutool.core.lang.Opt; -import cn.hutool.core.reflect.ClassUtil; -import cn.hutool.core.reflect.TypeUtil; -import cn.hutool.core.util.ServiceLoaderUtil; import javax.xml.datatype.XMLGregorianCalendar; import java.io.Serializable; @@ -78,6 +75,25 @@ import java.util.concurrent.atomic.AtomicReference; public class RegisterConverter implements Converter, Serializable { private static final long serialVersionUID = 1L; + /** + * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载 + */ + private static class SingletonHolder { + /** + * 静态初始化器,由JVM来保证线程安全 + */ + private static final CompositeConverter INSTANCE = new CompositeConverter(); + } + + /** + * 获得单例的 ConverterRegistry + * + * @return ConverterRegistry + */ + public static CompositeConverter getInstance() { + return RegisterConverter.SingletonHolder.INSTANCE; + } + /** * 默认类型转换器 */ @@ -92,7 +108,6 @@ public class RegisterConverter implements Converter, Serializable { */ public RegisterConverter() { registerDefault(); - registerCustomBySpi(); } @Override @@ -233,20 +248,4 @@ public class RegisterConverter implements Converter, Serializable { defaultConverterMap.put(Optional.class, new OptionalConverter());// since 5.0.0 defaultConverterMap.put(Opt.class, new OptConverter());// since 5.7.16 } - - /** - * 使用SPI加载转换器 - */ - private void registerCustomBySpi() { - ServiceLoaderUtil.load(Converter.class).forEach(converter -> { - try { - final Type type = TypeUtil.getTypeArgument(ClassUtil.getClass(converter)); - if (null != type) { - putCustom(type, converter); - } - } catch (final Exception ignore) { - // 忽略注册失败的 - } - }); - } } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java index 379afe302..324843a4b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/BeanConverter.java @@ -57,6 +57,11 @@ public class BeanConverter implements Converter, Serializable { return null; } + // value本身实现了Converter接口,直接调用 + if(value instanceof Converter){ + return ((Converter) value).convert(targetType, value); + } + Class targetClass = TypeUtil.getClass(targetType); Assert.notNull(targetClass, "Target type is not a class!"); @@ -79,6 +84,6 @@ public class BeanConverter implements Converter, Serializable { return SerializeUtil.deserialize((byte[]) value); } - throw new ConvertException("Unsupported source type: {}", value.getClass()); + throw new ConvertException("Unsupported source type: [{}] to [{}]", value.getClass(), targetType); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java index be6635a7a..a8b67a2d0 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/DateConverter.java @@ -67,7 +67,7 @@ public class DateConverter extends AbstractConverter { return wrap(targetClass, DateUtil.date((TemporalAccessor) value)); } else if (value instanceof Calendar) { return wrap(targetClass, DateUtil.date((Calendar) value)); - } else if (value instanceof Number) { + } else if (null == this.format && value instanceof Number) { return wrap(targetClass, ((Number) value).longValue()); } else { // 统一按照字符串处理 diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/MapConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/MapConverter.java index e1d733cdf..8a4eb3d4f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/MapConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/MapConverter.java @@ -67,7 +67,7 @@ public class MapConverter implements Converter, Serializable { // 二次转换,转换键值类型 map = convert(targetType, keyType, valueType, map); } else { - throw new UnsupportedOperationException(StrUtil.format("Unsupport toMap value type: {}", value.getClass().getName())); + throw new UnsupportedOperationException(StrUtil.format("Unsupported toMap value type: {}", value.getClass().getName())); } return map; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java index a12958a7d..6186c7d90 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiConsumer.java @@ -23,7 +23,7 @@ public interface SerBiConsumer extends BiConsumer, Serializable { * @return lambda */ @SafeVarargs - static SerBiConsumer multi(SerBiConsumer... consumers) { + static SerBiConsumer multi(final SerBiConsumer... consumers) { return Stream.of(consumers).reduce(SerBiConsumer::andThen).orElseGet(() -> (o, q) -> {}); } @@ -32,9 +32,8 @@ public interface SerBiConsumer extends BiConsumer, Serializable { * * @param t the first input argument * @param u the second input argument - * @throws Exception wrappered checked exceptions for easy using + * @throws Exception wrapped checked exceptions for easy using */ - @SuppressWarnings("all") void accepting(T t, U u) throws Exception; /** @@ -44,10 +43,10 @@ public interface SerBiConsumer extends BiConsumer, Serializable { * @param u the second input argument */ @Override - default void accept(T t, U u) { + default void accept(final T t, final U u) { try { accepting(t, u); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -64,7 +63,7 @@ public interface SerBiConsumer extends BiConsumer, Serializable { * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ - default SerBiConsumer andThen(SerBiConsumer after) { + default SerBiConsumer andThen(final SerBiConsumer after) { Objects.requireNonNull(after); return (l, r) -> { accepting(l, r); diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiFunction.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiFunction.java index fc903d90e..4b945959b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiFunction.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiFunction.java @@ -21,9 +21,8 @@ public interface SerBiFunction extends BiFunction, Serializabl * @param t the first function argument * @param u the second function argument * @return the function result - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") R applying(T t, U u) throws Exception; /** @@ -34,10 +33,10 @@ public interface SerBiFunction extends BiFunction, Serializabl * @return the function result */ @Override - default R apply(T t, U u) { + default R apply(final T t, final U u) { try { return this.applying(t, u); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -55,7 +54,7 @@ public interface SerBiFunction extends BiFunction, Serializabl * applies the {@code after} function * @throws NullPointerException if after is null */ - default SerBiFunction andThen(SerFunction after) { + default SerBiFunction andThen(final SerFunction after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(this.apply(t, u)); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiPredicate.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiPredicate.java index 74f50a0e1..f98a0036a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiPredicate.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBiPredicate.java @@ -23,9 +23,8 @@ public interface SerBiPredicate extends BiPredicate, Serializable { * @param u the second input argument * @return {@code true} if the input arguments match the predicate, * otherwise {@code false} - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") boolean testing(T t, U u) throws Exception; /** @@ -37,10 +36,10 @@ public interface SerBiPredicate extends BiPredicate, Serializable { * otherwise {@code false} */ @Override - default boolean test(T t, U u) { + default boolean test(final T t, final U u) { try { return testing(t, u); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -62,7 +61,7 @@ public interface SerBiPredicate extends BiPredicate, Serializable { * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default SerBiPredicate and(SerBiPredicate other) { + default SerBiPredicate and(final SerBiPredicate other) { Objects.requireNonNull(other); return (T t, U u) -> test(t, u) && other.test(t, u); } @@ -95,7 +94,7 @@ public interface SerBiPredicate extends BiPredicate, Serializable { * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default SerBiPredicate or(SerBiPredicate other) { + default SerBiPredicate or(final SerBiPredicate other) { Objects.requireNonNull(other); return (T t, U u) -> test(t, u) || other.test(t, u); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java index c8d9e1aa0..a416e3337 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerBinaryOperator.java @@ -22,9 +22,8 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { * @param t the first function argument * @param u the second function argument * @return the function result - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") T applying(T t, T u) throws Exception; /** @@ -35,10 +34,10 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { * @return the function result */ @Override - default T apply(T t, T u) { + default T apply(final T t, final T u) { try { return this.applying(t, u); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -53,7 +52,7 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ - static SerBinaryOperator minBy(Comparator comparator) { + static SerBinaryOperator minBy(final Comparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } @@ -68,7 +67,7 @@ public interface SerBinaryOperator extends BinaryOperator, Serializable { * according to the supplied {@code Comparator} * @throws NullPointerException if the argument is null */ - static SerBinaryOperator maxBy(Comparator comparator) { + static SerBinaryOperator maxBy(final Comparator comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java index 9a7312143..21a5464da 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer.java @@ -20,9 +20,8 @@ public interface SerConsumer extends Consumer, Serializable { * Performs this operation on the given argument. * * @param t the input argument - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") void accepting(T t) throws Exception; /** @@ -31,10 +30,10 @@ public interface SerConsumer extends Consumer, Serializable { * @param t the input argument */ @Override - default void accept(T t) { + default void accept(final T t) { try { accepting(t); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -47,7 +46,7 @@ public interface SerConsumer extends Consumer, Serializable { * @return lambda */ @SafeVarargs - static SerConsumer multi(SerConsumer... consumers) { + static SerConsumer multi(final SerConsumer... consumers) { return Stream.of(consumers).reduce(SerConsumer::andThen).orElseGet(() -> o -> {}); } @@ -63,7 +62,7 @@ public interface SerConsumer extends Consumer, Serializable { * operation followed by the {@code after} operation * @throws NullPointerException if {@code after} is null */ - default SerConsumer andThen(SerConsumer after) { + default SerConsumer andThen(final SerConsumer after) { Objects.requireNonNull(after); return (T t) -> { accept(t); diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java index 8997dd432..888d503d1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerConsumer3.java @@ -23,9 +23,8 @@ public interface SerConsumer3 extends Serializable { * @param p1 参数一 * @param p2 参数二 * @param p3 参数三 - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") void accepting(P1 p1, P2 p2, P3 p3) throws Exception; /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java index 5a0f98f3d..2e2c5b395 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerFunction.java @@ -19,9 +19,8 @@ public interface SerFunction extends Function, Serializable { * * @param t the function argument * @return the function result - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") R applying(T t) throws Exception; /** diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerPredicate.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerPredicate.java index 11479caff..85457df29 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerPredicate.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerPredicate.java @@ -22,7 +22,7 @@ public interface SerPredicate extends Predicate, Serializable { * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ boolean testing(T t) throws Exception; @@ -34,10 +34,10 @@ public interface SerPredicate extends Predicate, Serializable { * otherwise {@code false} */ @Override - default boolean test(T t) { + default boolean test(final T t) { try { return testing(t); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -50,7 +50,7 @@ public interface SerPredicate extends Predicate, Serializable { * @return lambda */ @SafeVarargs - static SerPredicate multiAnd(SerPredicate... predicates) { + static SerPredicate multiAnd(final SerPredicate... predicates) { return Stream.of(predicates).reduce(SerPredicate::and).orElseGet(() -> o -> true); } @@ -62,7 +62,7 @@ public interface SerPredicate extends Predicate, Serializable { * @return lambda */ @SafeVarargs - static SerPredicate multiOr(SerPredicate... predicates) { + static SerPredicate multiOr(final SerPredicate... predicates) { return Stream.of(predicates).reduce(SerPredicate::or).orElseGet(() -> o -> false); } @@ -76,7 +76,7 @@ public interface SerPredicate extends Predicate, Serializable { * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ - static SerPredicate isEqual(Object... targetRef) { + static SerPredicate isEqual(final Object... targetRef) { return (null == targetRef) ? Objects::isNull : object -> Stream.of(targetRef).allMatch(target -> target.equals(object)); @@ -98,7 +98,7 @@ public interface SerPredicate extends Predicate, Serializable { * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default SerPredicate and(SerPredicate other) { + default SerPredicate and(final SerPredicate other) { Objects.requireNonNull(other); return t -> test(t) && other.test(t); } @@ -131,7 +131,7 @@ public interface SerPredicate extends Predicate, Serializable { * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ - default SerPredicate or(SerPredicate other) { + default SerPredicate or(final SerPredicate other) { Objects.requireNonNull(other); return t -> test(t) || other.test(t); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerRunnable.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerRunnable.java index 17c8776c4..f9c3f9ed9 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerRunnable.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerRunnable.java @@ -24,10 +24,9 @@ public interface SerRunnable extends Runnable, Serializable { * The general contract of the method run is that it may * take any action whatsoever. * - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions * @see Thread#run() */ - @SuppressWarnings("all") void running() throws Exception; /** @@ -45,7 +44,7 @@ public interface SerRunnable extends Runnable, Serializable { default void run() { try { running(); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -56,7 +55,7 @@ public interface SerRunnable extends Runnable, Serializable { * @param serRunnableArray lambda * @return lambda */ - static SerRunnable multi(SerRunnable... serRunnableArray) { + static SerRunnable multi(final SerRunnable... serRunnableArray) { return () -> Stream.of(serRunnableArray).forEach(SerRunnable::run); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java index 09005e7a1..94d156b8b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerSupplier.java @@ -19,9 +19,8 @@ public interface SerSupplier extends Supplier, Serializable { * Gets a result. * * @return a result - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") T getting() throws Exception; /** @@ -33,7 +32,7 @@ public interface SerSupplier extends Supplier, Serializable { default T get() { try { return getting(); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -46,7 +45,7 @@ public interface SerSupplier extends Supplier, Serializable { * @return lambda */ @SafeVarargs - static SerSupplier last(SerSupplier... serSups) { + static SerSupplier last(final SerSupplier... serSups) { return Stream.of(serSups).reduce((l, r) -> r).orElseGet(() -> () -> null); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerUnaryOperator.java b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerUnaryOperator.java index 2b3c27ecd..bf6295228 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/func/SerUnaryOperator.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/func/SerUnaryOperator.java @@ -20,9 +20,8 @@ public interface SerUnaryOperator extends UnaryOperator, Serializable { * * @param t the function argument * @return the function result - * @throws Exception wrappered checked exceptions + * @throws Exception wrapped checked exceptions */ - @SuppressWarnings("all") T applying(T t) throws Exception; /** @@ -32,10 +31,10 @@ public interface SerUnaryOperator extends UnaryOperator, Serializable { * @return the function result */ @Override - default T apply(T t) { + default T apply(final T t) { try { return applying(t); - } catch (Exception e) { + } catch (final Exception e) { throw new UtilException(e); } } @@ -61,7 +60,7 @@ public interface SerUnaryOperator extends UnaryOperator, Serializable { * @return identity after casting */ @SuppressWarnings("unchecked") - static > SerUnaryOperator casting(F function) { + static > SerUnaryOperator casting(final F function) { return t -> (T) function.apply(t); } diff --git a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java index 3df4a2153..0e952b505 100755 --- a/hutool-core/src/main/java/cn/hutool/core/map/Dict.java +++ b/hutool-core/src/main/java/cn/hutool/core/map/Dict.java @@ -7,10 +7,11 @@ import cn.hutool.core.collection.SetUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.exceptions.CloneRuntimeException; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.lang.func.LambdaUtil; +import cn.hutool.core.lang.func.SerSupplier; import cn.hutool.core.lang.getter.BasicTypeGetter; +import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.Time; @@ -564,7 +565,7 @@ public class Dict extends CustomKeyMap implements BasicTypeGette * @see BeanPath#get(Object) * @since 5.7.14 */ - public T getByPath(final String expression, final Class resultType) { + public T getByPath(final String expression, final Type resultType) { return Convert.convert(resultType, getByPath(expression)); } // -------------------------------------------------------------------- Get end @@ -573,7 +574,7 @@ public class Dict extends CustomKeyMap implements BasicTypeGette public Dict clone() { try { return (Dict) super.clone(); - } catch (CloneNotSupportedException e) { + } catch (final CloneNotSupportedException e) { throw new CloneRuntimeException(e); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java index 0d5b22f14..90de48122 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/EasyStream.java @@ -342,7 +342,7 @@ public class EasyStream extends AbstractEnhancedWrappedStream>> recursiveRef = new MutableObj<>(); final Consumer> recursive = values -> EasyStream.of(values, isParallel()).forEach(value -> { - List children = pIdValuesMap.get(idGetter.apply(value)); + final List children = pIdValuesMap.get(idGetter.apply(value)); childrenSetter.accept(value, children); recursiveRef.get().accept(children); }); diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java index ba5f73f47..17344f511 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TerminableWrappedStream.java @@ -17,52 +17,52 @@ import java.util.stream.Stream; * * @param 流中的元素类型 * @param {@link TerminableWrappedStream}的实现类类型 - * @author huangchengxing VampireAchao + * @author huangchengxing * @since 6.0.0 */ public interface TerminableWrappedStream> extends WrappedStream { - // region ============ to collection ============ + // region ============ to collection ============ - /** - * 转换为{@link ArrayList} - * - * @return 集合 + /** + * 转换为{@link ArrayList} + * + * @return 集合 + * @see #toColl(Supplier) + */ + default List toList() { + return this.toColl(ArrayList::new); + } + + /** + * 换为不可变集合 + * + * @return 集合 * @see #toColl(Supplier) */ - default List toList() { - return this.toColl(ArrayList::new); - } + default List toUnmodifiableList() { + return Collections.unmodifiableList(this.toList()); + } - /** - * 换为不可变集合 - * - * @return 集合 + /** + * 转换为HashSet + * + * @return 集合 * @see #toColl(Supplier) */ - default List toUnmodifiableList() { - return Collections.unmodifiableList(this.toList()); - } + default Set toSet() { + return this.toColl(HashSet::new); + } - /** - * 转换为HashSet - * - * @return 集合 + /** + * 换为不可变集合 + * + * @return 集合 * @see #toColl(Supplier) */ - default Set toSet() { - return this.toColl(HashSet::new); - } - - /** - * 换为不可变集合 - * - * @return 集合 - * @see #toColl(Supplier) - */ - default Set toUnmodifiableSet() { - return Collections.unmodifiableSet(this.toSet()); - } + default Set toUnmodifiableSet() { + return Collections.unmodifiableSet(this.toSet()); + } /** * 转换成集合 @@ -76,145 +76,145 @@ public interface TerminableWrappedStream key类型 - * @return map + /** + * 转换为map,key为给定操作执行后的返回值,value为当前元素 + * + * @param keyMapper 指定的key操作 + * @param key类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap(final Function keyMapper) { - return this.toMap(keyMapper, Function.identity()); - } + */ + default Map toMap(final Function keyMapper) { + return this.toMap(keyMapper, Function.identity()); + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap( - final Function keyMapper, final Function valueMapper) { - return this.toMap(keyMapper, valueMapper, (l, r) -> r); - } + */ + default Map toMap( + final Function keyMapper, final Function valueMapper) { + return this.toMap(keyMapper, valueMapper, (l, r) -> r); + } - /** - * 转换为不可变map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为不可变map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toUnmodifiableMap( - final Function keyMapper, final Function valueMapper) { - return Collections.unmodifiableMap(this.toMap(keyMapper, valueMapper)); - } + */ + default Map toUnmodifiableMap( + final Function keyMapper, final Function valueMapper) { + return Collections.unmodifiableMap(this.toMap(keyMapper, valueMapper)); + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toMap( - final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction) { - return this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); - } + */ + default Map toMap( + final Function keyMapper, + final Function valueMapper, + final BinaryOperator mergeFunction) { + return this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new); + } - /** - * 转换为不可变map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param key类型 - * @param value类型 - * @return map + /** + * 转换为不可变map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param key类型 + * @param value类型 + * @return map * @see #toMap(Function, Function, BinaryOperator, Supplier) - */ - default Map toUnmodifiableMap( - final Function keyMapper, - final Function valueMapper, - final BinaryOperator mergeFunction) { - return Collections.unmodifiableMap( - this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new) + */ + default Map toUnmodifiableMap( + final Function keyMapper, + final Function valueMapper, + final BinaryOperator mergeFunction) { + return Collections.unmodifiableMap( + this.toMap(keyMapper, valueMapper, mergeFunction, HashMap::new) ); - } + } - /** - * 转换为map,key,value为给定操作执行后的返回值 - * - * @param keyMapper 指定的key操作 - * @param valueMapper 指定value操作 - * @param mergeFunction 合并操作 - * @param mapSupplier map工厂 - * @param key类型 - * @param value类型 - * @param map类型 - * @return map - */ - default > M toMap( + /** + * 转换为map,key,value为给定操作执行后的返回值 + * + * @param keyMapper 指定的key操作 + * @param valueMapper 指定value操作 + * @param mergeFunction 合并操作 + * @param mapSupplier map工厂 + * @param key类型 + * @param value类型 + * @param map类型 + * @return map + */ + default > M toMap( final Function keyMapper, final Function valueMapper, final BinaryOperator mergeFunction, - Supplier mapSupplier) { + final Supplier mapSupplier) { Objects.requireNonNull(keyMapper); Objects.requireNonNull(valueMapper); Objects.requireNonNull(mergeFunction); Objects.requireNonNull(mapSupplier); - return unwrap().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier)); - } + return unwrap().collect(Collectors.toMap(keyMapper, valueMapper, mergeFunction, mapSupplier)); + } - // endregion + // endregion - // region ============ to zip ============ + // region ============ to zip ============ - /** - * 与给定的可迭代对象转换成map,key为现有元素,value为给定可迭代对象迭代的元素
- * 至少包含全部的key,如果对应位置上的value不存在,则为null - * - * @param other 可迭代对象 - * @param 可迭代对象迭代的元素类型 - * @return map,key为现有元素,value为给定可迭代对象迭代的元素;
- * 至少包含全部的key,如果对应位置上的value不存在,则为null;
- * 如果key重复, 则保留最后一个关联的value;
- */ - default Map toZip(final Iterable other) { + /** + * 与给定的可迭代对象转换成map,key为现有元素,value为给定可迭代对象迭代的元素
+ * 至少包含全部的key,如果对应位置上的value不存在,则为null + * + * @param other 可迭代对象 + * @param 可迭代对象迭代的元素类型 + * @return map,key为现有元素,value为给定可迭代对象迭代的元素;
+ * 至少包含全部的key,如果对应位置上的value不存在,则为null;
+ * 如果key重复, 则保留最后一个关联的value;
+ */ + default Map toZip(final Iterable other) { Objects.requireNonNull(other); - // value对象迭代器 - final Iterator iterator = Opt.ofNullable(other).map(Iterable::iterator).orElseGet(Collections::emptyIterator); - if (this.isParallel()) { + // value对象迭代器 + final Iterator iterator = Opt.ofNullable(other).map(Iterable::iterator).orElseGet(Collections::emptyIterator); + if (this.isParallel()) { final List keyList = toList(); - final Map map = new HashMap<>(keyList.size()); - for (T key : keyList) { - map.put(key, iterator.hasNext() ? iterator.next() : null); - } - return map; - } else { - return this.toMap(Function.identity(), e -> iterator.hasNext() ? iterator.next() : null); - } - } + final Map map = new HashMap<>(keyList.size()); + for (final T key : keyList) { + map.put(key, iterator.hasNext() ? iterator.next() : null); + } + return map; + } else { + return this.toMap(Function.identity(), e -> iterator.hasNext() ? iterator.next() : null); + } + } - // endregion + // endregion // region ============ to optional ============ @@ -408,7 +408,7 @@ public interface TerminableWrappedStream Map group( - final Function classifier, final Collector downstream) { + final Function classifier, final Collector downstream) { return this.group(classifier, HashMap::new, downstream); } @@ -426,9 +426,9 @@ public interface TerminableWrappedStream> M group( - final Function classifier, - final Supplier mapFactory, - final Collector downstream) { + final Function classifier, + final Supplier mapFactory, + final Collector downstream) { Objects.requireNonNull(classifier); Objects.requireNonNull(mapFactory); Objects.requireNonNull(downstream); @@ -449,9 +449,9 @@ public interface TerminableWrappedStream 值类型 + * @param predicate 判断条件 * @param collFactory 提供的集合 - * @param 集合类型 * @return map * @see #partition(Predicate, Collector) */ @@ -464,7 +464,7 @@ public interface TerminableWrappedStream 返回值类型 + * @param 返回值类型 * @return map */ default Map partition(final Predicate predicate, final Collector downstream) { diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java index 698005ca8..d621278da 100644 --- a/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java +++ b/hutool-core/src/main/java/cn/hutool/core/stream/TransformableWrappedStream.java @@ -3,6 +3,7 @@ package cn.hutool.core.stream; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.collection.iter.IterUtil; import cn.hutool.core.lang.Console; +import cn.hutool.core.lang.Opt; import cn.hutool.core.lang.mutable.MutableInt; import cn.hutool.core.lang.mutable.MutableObj; import cn.hutool.core.map.MapUtil; @@ -23,7 +24,7 @@ import java.util.stream.StreamSupport; * * @param 流中的元素类型 * @param {@link TransformableWrappedStream}的实现类类型 - * @author huangchengxing VampireAchao + * @author huangchengxing * @since 6.0.0 */ public interface TransformableWrappedStream> extends WrappedStream { @@ -39,15 +40,24 @@ public interface TransformableWrappedStream EasyStream zip( - final Iterable other, - final BiFunction zipper) { + final Iterable other, + final BiFunction zipper) { Objects.requireNonNull(zipper); - Map idxIdentityMap = mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap()); - Map idxOtherMap = EasyStream.of(other).mapIdx((e, idx) -> MapUtil.entry(idx, e)).collect(CollectorUtil.entryToMap()); - if (idxIdentityMap.size() <= idxOtherMap.size()) { - return EasyStream.of(idxIdentityMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k))); + final Spliterator keys = spliterator(); + final Spliterator values = Opt.ofNullable(other).map(Iterable::spliterator).orElseGet(Spliterators::emptySpliterator); + // 获取两个Spliterator的中较小的数量 + // 如果Spliterator经过流操作, getExactSizeIfKnown()可能会返回-1, 所以默认大小为 ArrayList.DEFAULT_CAPACITY + final int sizeIfKnown = (int) Math.max(Math.min(keys.getExactSizeIfKnown(), values.getExactSizeIfKnown()), 10); + final List list = new ArrayList<>(sizeIfKnown); + // 保存第一个Spliterator的值 + final MutableObj key = new MutableObj<>(); + // 保存第二个Spliterator的值 + final MutableObj value = new MutableObj<>(); + // 当两个Spliterator中都还有剩余元素时 + while (keys.tryAdvance(key::set) && values.tryAdvance(value::set)) { + list.add(zipper.apply(key.get(), value.get())); } - return EasyStream.of(idxOtherMap.keySet(), isParallel()).map(k -> zipper.apply(idxIdentityMap.get(k), idxOtherMap.get(k))); + return EasyStream.of(list).parallel(isParallel()).onClose(unwrap()::close); } /** @@ -68,9 +78,9 @@ public interface TransformableWrappedStream>of(EasyStream.of(list, isParallel())); } return EasyStream.iterate(0, i -> i < size, i -> i + batchSize) - .map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel())) - .parallel(isParallel()) - .onClose(unwrap()::close); + .map(skip -> EasyStream.of(list.subList(skip, Math.min(size, skip + batchSize)), isParallel())) + .parallel(isParallel()) + .onClose(unwrap()::close); } /** @@ -104,8 +114,8 @@ public interface TransformableWrappedStream 键类型 + * @param keyMapper 键的映射方法 + * @param 键类型 * @return {@link EntryStream}实例 */ default EntryStream toEntries(final Function keyMapper) { @@ -145,10 +155,11 @@ public interface TransformableWrappedStream elements = unwrap().collect(Collectors.toList()); return wrap(ListUtil.splice(elements, start, deleteCount, items).stream()) - .parallel(isParallel()); + .parallel(isParallel()); } /** @@ -181,15 +192,15 @@ public interface TransformableWrappedStream * eg: *
{@code
 	 * EasyStream.of(1, 2, 3, 4, 5)
 	 * 	.dropWhile(i -> !Objects.equals(3, i)) // 删除不为3的元素,一直到遇到第一个3为止
 	 * 	.toList(); // = [3, 4, 5]
 	 * }
- *

- * 与{@code JDK9}中的{@code dropWhile}方法不太一样,此操作为顺序且有状态的中间操作。 + * + *

与{@code JDK9}中的{@code dropWhile}方法不太一样,此操作为顺序且有状态的中间操作。 * 即使在并行流中,该操作仍然是顺序执行的,并且不影响后续的并行操作: *

{@code
 	 * EasyStream.iterate(1, i -> i + 1)
@@ -251,7 +262,6 @@ public interface TransformableWrappedStream action.accept(e, NOT_FOUND_ELEMENT_INDEX));
 		} else {
-			AtomicInteger index = new AtomicInteger(NOT_FOUND_ELEMENT_INDEX);
+			final AtomicInteger index = new AtomicInteger(NOT_FOUND_ELEMENT_INDEX);
 			return peek(e -> action.accept(e, index.incrementAndGet()));
 		}
 	}
@@ -309,6 +319,7 @@ public interface TransformableWrappedStream result = unwrap();
 		if (ArrayUtil.isNotEmpty(obj)) {
@@ -480,9 +491,10 @@ public interface TransformableWrappedStream>> recursiveRef = new MutableObj<>();
+		@SuppressWarnings("unchecked")
 		final Function> recursive = e -> EasyStream.of(childrenGetter.apply(e))
-				.flat(recursiveRef.get())
-				.unshift(e);
+			.flat(recursiveRef.get())
+			.unshift(e);
 		recursiveRef.set(recursive);
 		return wrap(flatMap(recursive).peek(e -> childrenSetter.accept(e, null)));
 	}
diff --git a/hutool-core/src/main/java/cn/hutool/core/stream/WrappedStream.java b/hutool-core/src/main/java/cn/hutool/core/stream/WrappedStream.java
index 8f9399f16..7e503226a 100644
--- a/hutool-core/src/main/java/cn/hutool/core/stream/WrappedStream.java
+++ b/hutool-core/src/main/java/cn/hutool/core/stream/WrappedStream.java
@@ -269,6 +269,7 @@ public interface WrappedStream> extends Stream<
 	@Override
 	default  A[] toArray(final IntFunction generator) {
 		Objects.requireNonNull(generator);
+		//noinspection SuspiciousToArrayCall
 		return unwrap().toArray(generator);
 	}
 
@@ -547,7 +548,7 @@ public interface WrappedStream> extends Stream<
 	 * @return 流
 	 */
 	@Override
-	default S onClose(Runnable closeHandler) {
+	default S onClose(final Runnable closeHandler) {
 		return wrap(unwrap().onClose(closeHandler));
 	}
 
diff --git a/hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java b/hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java
new file mode 100755
index 000000000..6cf936efd
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/text/dfa/issueI5Q4HDTest.java
@@ -0,0 +1,25 @@
+package cn.hutool.core.text.dfa;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class issueI5Q4HDTest {
+
+	@Test
+	public void matchAllTest(){
+		final String content="站房建设面积较小,不符合规范要求。辅助设施_站房_面积";
+		final String keywordStr="不符合规范要求,现场手工比对孔不规范,采样口,现场,辅助设施,比对孔未处于监测断面下游,站房,未设置,标识,给排水,面积较小,监控设备,灭火装置,排污口,设备操作维护不方便,不规范,采样平台,参比方法,直爬梯,单独,站房建设,不健全,没有配置";
+		final List keyWords = Arrays.asList(keywordStr.split(","));
+		final Set keyWordSet=new HashSet<>(keyWords);
+		final WordTree wordTree=new WordTree();
+		wordTree.addWords(keyWordSet);
+		//DateUtil.beginOfHour()
+		final List strings = wordTree.matchAll(content, -1, true, true);
+		Assert.assertEquals("[站房, 站房建设, 面积较小, 不符合规范要求, 辅助设施, 站房]", strings.toString());
+	}
+}
diff --git a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java
index 320d0a790..60f92b02b 100644
--- a/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java
+++ b/hutool-crypto/src/test/java/cn/hutool/crypto/asymmetric/SM2Test.java
@@ -31,6 +31,8 @@ public class SM2Test {
 		final KeyPair pair = KeyUtil.generateKeyPair("SM2");
 		Assert.assertNotNull(pair.getPrivate());
 		Assert.assertNotNull(pair.getPublic());
+
+		new SM2(pair.getPrivate(), pair.getPublic());
 	}
 
 	@Test
@@ -319,4 +321,9 @@ public class SM2Test {
 		// 04占位一个字节
 		Assert.assertEquals(65, sm2.getQ(false).length);
 	}
+
+	@Test
+	public void issuesI5PWQ4Test(){
+
+	}
 }
diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java
index df7301f9d..3c634c988 100755
--- a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java
+++ b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java
@@ -1022,6 +1022,7 @@ public class HttpRequest extends HttpBase {
 	 *
 	 * @param  结果类型
 	 * @param function 响应内容处理函数
+	 * @return 结果值
 	 * @since 5.8.5
 	 */
 	public  T thenFunction(final Function function) {
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java
index c0c1f3a7c..134cc98b1 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSON.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java
@@ -1,7 +1,10 @@
 package cn.hutool.json;
 
 import cn.hutool.core.bean.BeanPath;
+import cn.hutool.core.convert.ConvertException;
+import cn.hutool.core.convert.Converter;
 import cn.hutool.core.lang.mutable.MutableEntry;
+import cn.hutool.json.convert.JSONConverter;
 
 import java.io.Serializable;
 import java.io.StringWriter;
@@ -14,7 +17,7 @@ import java.util.function.Predicate;
  *
  * @author Looly
  */
-public interface JSON extends Cloneable, Serializable {
+public interface JSON extends Converter, Cloneable, Serializable {
 
 	/**
 	 * 获取JSON配置
@@ -171,6 +174,11 @@ public interface JSON extends Cloneable, Serializable {
 	 */
 	@SuppressWarnings("unchecked")
 	default  T toBean(final Type type) {
-		return (T) getConfig().getConverter().convert(type, this);
+		return (T) convert(type, this);
+	}
+
+	@Override
+	default Object convert(Type targetType, Object value) throws ConvertException {
+		return JSONConverter.of(getConfig()).convert(targetType, value);
 	}
 }
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
index c8ca774b3..a06d61190 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
@@ -13,7 +13,6 @@ import cn.hutool.json.serialize.JSONWriter;
 
 import java.io.StringWriter;
 import java.io.Writer;
-import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
@@ -231,11 +230,6 @@ public class JSONArray implements JSON, JSONGetter, List, Rando
 		return this;
 	}
 
-	@Override
-	public  T toBean(final Type type) {
-		return JSON.super.toBean(type);
-	}
-
 	/**
 	 * 根据给定名列表,与其位置对应的值组成JSONObject
 	 *
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java b/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java
index 2e2526b82..8a01af8ab 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONConfig.java
@@ -1,10 +1,18 @@
 package cn.hutool.json;
 
 import cn.hutool.core.comparator.CompareUtil;
+import cn.hutool.core.convert.Convert;
 import cn.hutool.core.convert.Converter;
+import cn.hutool.core.convert.impl.DateConverter;
+import cn.hutool.core.convert.impl.TemporalAccessorConverter;
+import cn.hutool.core.reflect.TypeUtil;
+import cn.hutool.core.text.StrUtil;
+import cn.hutool.json.convert.JSONConverter;
 
 import java.io.Serializable;
+import java.time.temporal.TemporalAccessor;
 import java.util.Comparator;
+import java.util.Date;
 
 /**
  * JSON配置项
@@ -50,7 +58,33 @@ public class JSONConfig implements Serializable {
 	/**
 	 * 自定义的类型转换器,用于在序列化、反序列化操作中实现对象类型转换
 	 */
-	private Converter converter;
+	private Converter converter = (type, value)->{
+		final Class rawType = TypeUtil.getClass(type);
+		if(null == rawType){
+			return value;
+		}
+		if(JSON.class.isAssignableFrom(rawType)){
+			return JSONConverter.INSTANCE.toJSON(value);
+		}
+		if(Date.class.isAssignableFrom(rawType) || TemporalAccessor.class.isAssignableFrom(rawType)){
+			// 用户指定了日期格式,获取日期属性时使用对应格式
+			final String valueStr = Convert.convertWithCheck(String.class, value, null, isIgnoreError());
+			if (null == valueStr) {
+				return null;
+			}
+
+			// 日期转换,支持自定义日期格式
+			final String format = getDateFormat();
+			if (StrUtil.isNotBlank(format)) {
+				if (Date.class.isAssignableFrom(rawType)) {
+					return new DateConverter(format).convert(type, value);
+				} else {
+					return new TemporalAccessorConverter(format).convert(type, value);
+				}
+			}
+		}
+		return Convert.convertWithCheck(type, value, null, isIgnoreError());
+	};
 
 	/**
 	 * 创建默认的配置项
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java
index 645a41d60..6179a5d1c 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java
@@ -10,7 +10,6 @@ import cn.hutool.json.serialize.JSONWriter;
 
 import java.io.StringWriter;
 import java.io.Writer;
-import java.lang.reflect.Type;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Collection;
@@ -150,11 +149,6 @@ public class JSONObject extends MapWrapper implements JSON, JSON
 		return this;
 	}
 
-	@Override
-	public  T toBean(final Type type) {
-		return JSON.super.toBean(type);
-	}
-
 	/**
 	 * 将指定KEY列表的值组成新的JSONArray
 	 *
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java
index 2e170d320..2f6ea18a2 100644
--- a/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONSupport.java
@@ -1,6 +1,6 @@
 package cn.hutool.json;
 
-import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.BeanCopier;
 import cn.hutool.json.serialize.JSONDeserializer;
 import cn.hutool.json.serialize.JSONString;
 
@@ -28,8 +28,9 @@ public class JSONSupport implements JSONString, JSONDeserializer {
 	 */
 	@Override
 	public Object deserialize(final JSON json) {
-		// TODO 经过两次转换,效率差,待优化
-		BeanUtil.copyProperties(json.toBean(getClass()), this);
+		BeanCopier.of(json,
+				this, this.getClass(),
+				InternalJSONUtil.toCopyOptions(json.getConfig())).copy();
 		return this;
 	}
 
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java
index 28a38f2be..4f52ded37 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONUtil.java
@@ -141,7 +141,7 @@ public class JSONUtil {
 	 * @return JSON
 	 */
 	public static JSON parse(final Object obj) {
-		return JSONConverter.INSTANCE.convert(obj);
+		return JSONConverter.INSTANCE.toJSON(obj);
 	}
 
 	/**
@@ -159,7 +159,7 @@ public class JSONUtil {
 	 * @since 5.3.1
 	 */
 	public static JSON parse(final Object obj, final JSONConfig config) {
-		return JSONConverter.of(config).convert(obj);
+		return JSONConverter.of(config).toJSON(obj);
 	}
 
 	/**
diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java
deleted file mode 100755
index 709899b03..000000000
--- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONCompositeConverter.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package cn.hutool.json.convert;
-
-import cn.hutool.core.convert.CompositeConverter;
-import cn.hutool.core.convert.ConvertException;
-
-import java.lang.reflect.Type;
-
-public class JSONCompositeConverter extends CompositeConverter {
-
-	public static final JSONCompositeConverter INSTANCE = new JSONCompositeConverter();
-
-	@Override
-	public  T convert(final Type type, final Object value, final T defaultValue, final boolean isCustomFirst) throws ConvertException {
-		return super.convert(type, value, defaultValue, isCustomFirst);
-	}
-}
diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java
index 8422c42b7..96748a5f9 100644
--- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java
+++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONConverter.java
@@ -1,18 +1,33 @@
 package cn.hutool.json.convert;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.bean.copier.BeanCopier;
 import cn.hutool.core.convert.ConvertException;
 import cn.hutool.core.convert.Converter;
+import cn.hutool.core.convert.RegisterConverter;
+import cn.hutool.core.convert.impl.ArrayConverter;
+import cn.hutool.core.convert.impl.CollectionConverter;
+import cn.hutool.core.convert.impl.MapConverter;
 import cn.hutool.core.map.MapWrapper;
+import cn.hutool.core.reflect.ConstructorUtil;
+import cn.hutool.core.reflect.TypeReference;
+import cn.hutool.core.reflect.TypeUtil;
 import cn.hutool.core.text.StrUtil;
 import cn.hutool.core.util.ArrayUtil;
+import cn.hutool.json.InternalJSONUtil;
 import cn.hutool.json.JSON;
 import cn.hutool.json.JSONArray;
 import cn.hutool.json.JSONConfig;
+import cn.hutool.json.JSONException;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
+import cn.hutool.json.serialize.GlobalSerializeMapping;
+import cn.hutool.json.serialize.JSONDeserializer;
 
 import java.lang.reflect.Type;
+import java.util.Collection;
 import java.util.Iterator;
+import java.util.Map;
 
 /**
  * JSON转换器,实现Object对象转换为{@link JSON},支持的对象:
@@ -28,6 +43,11 @@ import java.util.Iterator;
 public class JSONConverter implements Converter {
 	public static final JSONConverter INSTANCE = new JSONConverter(null);
 
+	static {
+		RegisterConverter.getInstance().putCustom(JSONObject.class, INSTANCE);
+		RegisterConverter.getInstance().putCustom(JSONArray.class, INSTANCE);
+	}
+
 	/**
 	 * 创建JSON转换器
 	 *
@@ -49,6 +69,30 @@ public class JSONConverter implements Converter {
 		this.config = config;
 	}
 
+	@Override
+	public Object convert(Type targetType, final Object obj) throws ConvertException {
+		if (null == obj) {
+			return null;
+		}
+
+		// 对象转JSON
+		if (targetType instanceof JSON) {
+			return toJSON(obj);
+		}
+
+		// JSON转对象
+		if (obj instanceof JSON) {
+			if (targetType instanceof TypeReference) {
+				targetType = ((TypeReference) targetType).getType();
+			}
+			return toBean(targetType, (JSON) obj);
+		}
+
+		// 无法转换
+		throw new JSONException("Can not convert from {}: [{}] to [{}]",
+				obj.getClass().getName(), obj, targetType.getTypeName());
+	}
+
 	/**
 	 * 实现Object对象转换为{@link JSON},支持的对象:
 	 * 
    @@ -59,17 +103,9 @@ public class JSONConverter implements Converter { * * @param obj 被转换的对象 * @return 转换后的对象 - * @throws ConvertException 转换异常 + * @throws JSONException 转换异常 */ - public JSON convert(final Object obj) throws ConvertException { - return (JSON) convert(null, obj); - } - - @Override - public Object convert(final Type targetType, final Object obj) throws ConvertException { - if (null == obj) { - return null; - } + public JSON toJSON(final Object obj) throws JSONException { final JSON json; if (obj instanceof JSON) { json = (JSON) obj; @@ -87,4 +123,99 @@ public class JSONConverter implements Converter { return json; } + + @SuppressWarnings("unchecked") + private T toBean(final Type targetType, final JSON json) { + final Class rawType = (Class) TypeUtil.getClass(targetType); + if(null != rawType && JSONDeserializer.class.isAssignableFrom(rawType)){ + return (T) JSONDeserializerConverter.INSTANCE.convert(targetType, json); + } + + // 全局自定义反序列化(优先级低于实现JSONDeserializer接口) + final JSONDeserializer deserializer = GlobalSerializeMapping.getDeserializer(targetType); + if (null != deserializer) { + return (T) deserializer.deserialize(json); + } + + // 其他转换不支持非Class的泛型类型 + if (null == rawType) { + throw new JSONException("Can not get class from type: {}", targetType); + } + // 特殊类型转换,包括Collection、Map、强转、Array等 + final T result = toSpecial(targetType, rawType, json); + if (null != result) { + return result; + } + + // 标准转换器 + final Converter converter = RegisterConverter.getInstance().getConverter(targetType, true); + if (null != converter) { + return (T) converter.convert(targetType, json); + } + + // 尝试转Bean + if (BeanUtil.isBean(rawType)) { + return BeanCopier.of(json, + ConstructorUtil.newInstanceIfPossible(rawType), targetType, + InternalJSONUtil.toCopyOptions(json.getConfig())).copy(); + } + + // 跳过异常时返回null + if(json.getConfig().isIgnoreError()){ + return null; + } + + // 无法转换 + throw new JSONException("Can not convert from {}: [{}] to [{}]", + json.getClass().getName(), json, targetType.getTypeName()); + } + + // ----------------------------------------------------------- Private method start + + /** + * 特殊类型转换
    + * 包括: + * + *
    +	 * Collection
    +	 * Map
    +	 * 强转(无需转换)
    +	 * 数组
    +	 * 
    + * + * @param 转换的目标类型(转换器转换到的类型) + * @param type 类型 + * @param value 值 + * @return 转换后的值 + */ + @SuppressWarnings("unchecked") + private T toSpecial(final Type type, final Class rowType, final JSON value) { + if (null == rowType) { + return null; + } + + // 集合转换(含有泛型参数,不可以默认强转) + if (Collection.class.isAssignableFrom(rowType)) { + return (T) CollectionConverter.INSTANCE.convert(type, value); + } + + // Map类型(含有泛型参数,不可以默认强转) + if (Map.class.isAssignableFrom(rowType)) { + return (T) MapConverter.INSTANCE.convert(type, value); + } + + // 默认强转 + if (rowType.isInstance(value)) { + return (T) value; + } + + // 数组转换 + if (rowType.isArray()) { + return (T) ArrayConverter.INSTANCE.convert(type, value); + } + + // 表示非需要特殊转换的对象 + return null; + } + // ----------------------------------------------------------- Private method end } diff --git a/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java b/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java index c23e8799a..cd7c92d35 100644 --- a/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java +++ b/hutool-json/src/main/java/cn/hutool/json/convert/JSONDeserializerConverter.java @@ -15,6 +15,8 @@ import cn.hutool.json.serialize.JSONDeserializer; public class JSONDeserializerConverter extends AbstractConverter { private static final long serialVersionUID = 1L; + public static final JSONDeserializerConverter INSTANCE = new JSONDeserializerConverter(); + @Override protected Object convertInternal(final Class targetClass, final Object value) { // 自定义反序列化 diff --git a/hutool-json/src/test/java/Issue2555Test.java b/hutool-json/src/test/java/cn/hutool/json/Issue2555Test.java old mode 100755 new mode 100644 similarity index 98% rename from hutool-json/src/test/java/Issue2555Test.java rename to hutool-json/src/test/java/cn/hutool/json/Issue2555Test.java index d62c63bb5..c020737b9 --- a/hutool-json/src/test/java/Issue2555Test.java +++ b/hutool-json/src/test/java/cn/hutool/json/Issue2555Test.java @@ -1,3 +1,5 @@ +package cn.hutool.json; + import cn.hutool.json.JSON; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index 709801136..283e05303 100755 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -472,7 +472,7 @@ public class JSONObjectTest { @Test public void setDateFormatTest3() { - // 自定义格式为只有秒的时间戳,一版用于JWT + // 自定义格式为只有秒的时间戳,一般用于JWT final JSONConfig jsonConfig = JSONConfig.of().setDateFormat("#sss"); final Date date = DateUtil.parse("2020-06-05 11:16:11"); diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI5Q1TWTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI5Q1TWTest.java new file mode 100755 index 000000000..7e79cc46d --- /dev/null +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/IssueI5Q1TWTest.java @@ -0,0 +1,18 @@ +package cn.hutool.poi.excel; + +import cn.hutool.core.lang.Console; +import org.junit.Ignore; +import org.junit.Test; + +import java.util.List; + +public class IssueI5Q1TWTest { + + @Test + @Ignore + public void readTest(){ + final ExcelReader reader = ExcelUtil.getReader("d:/test/I5Q1TW.xlsx"); + final List> read = reader.read(); + Console.log(reader.readCellValue(0, 0)); + } +}