diff --git a/CHANGELOG.md b/CHANGELOG.md index 101e9ebe1..82628bad3 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ ------------------------------------------------------------------------------------------------------------- +# 5.8.1 (2022-05-16) + +### 🐣新特性 +* 【core 】 BooleanUtil增加toBooleanObject方法(issue#I56AG3@Gitee) +* 【core 】 CharSequenceUtil增加startWithAnyIgnoreCase方法(issue#2312@Github) +* 【system 】 JavaInfo增加版本(issue#2310@Github) +* 【core 】 新增CastUtil(pr#2313@Github) +* 【core 】 ByteUtil新增bytesToShort重载(issue#I57FA7@Gitee) +* 【core 】 ReflectUtil.invoke方法抛出运行时异常增加InvocationTargetRuntimeException(issue#I57GI2@Gitee) +* 【core 】 NumberUtil.parseNumber支持16进制(issue#2328@Github) +* +### 🐞Bug修复 +* 【core 】 MapUtil.map对null友好,且修复了测试用例中分组问题(pr#614@Gitee) +* 【core 】 修复BeanUtil.beanToMap中properties为null的空指针问题(issue#2303@Github) +* 【db 】 DialectName中修正为POSTGRESQL(issue#2308@Github) +* 【core 】 修复BeanPath无法识别引号内的内容问题(issue#I56DE0@Gitee) +* 【core 】 修复Map.entry方法返回可变不可变相反问题 +* 【jwt 】 修复jwt的过期容忍时间问题(issue#2329@Gitee) + +------------------------------------------------------------------------------------------------------------- + # 5.8.0 (2022-05-06) ### ❌不兼容特性 @@ -174,4 +195,7 @@ * 【core 】 FileUtil.getMimeType增加rar、7z支持(issue#I4ZBN0@Gitee) * 【json 】 JSON修复transient设置无效问题(issue#2212@Github) * 【core 】 修复IterUtil.getElementType获取结果为null的问题(issue#2222@Github) -* 【core 】 修复农历转公历在闰月时错误(issue#I4ZSGJ@Gitee) \ No newline at end of file +* 【core 】 修复农历转公历在闰月时错误(issue#I4ZSGJ@Gitee) + +# 5.7.x 或更早版本 +* [https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md](https://gitee.com/dromara/hutool/blob/v5-master/CHANGELOG_5.0-5.7.md) \ No newline at end of file diff --git a/README-EN.md b/README-EN.md index a9fb50154..8759c4f23 100755 --- a/README-EN.md +++ b/README-EN.md @@ -144,18 +144,18 @@ We provide the T-Shirt and Sweater with Hutool Logo, please visit the shop: cn.hutool hutool-all - 5.8.0 + 5.8.1 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.0' +implementation 'cn.hutool:hutool-all:5.8.1' ``` ## 📥Download -- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.0/) +- [Maven Repo](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.1/) > 🔔️note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index f709e87d1..278a93ea9 100755 --- a/README.md +++ b/README.md @@ -144,20 +144,20 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.8.0 + 5.8.1 ``` ### 🍐Gradle ``` -implementation 'cn.hutool:hutool-all:5.8.0' +implementation 'cn.hutool:hutool-all:5.8.1' ``` ### 📥下载jar 点击以下链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.0/) +- [Maven中央库](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.8.1/) > 🔔️注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 11d9efa3d..1802e771b 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.8.0 +5.8.1 diff --git a/docs/js/version.js b/docs/js/version.js index d7dea1709..5b86fe85e 100755 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.8.0' \ No newline at end of file +var version = '5.8.1' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 764f45852..26270b92e 100755 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index e8241a598..9cd1c6eae 100755 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-aop @@ -19,7 +19,7 @@ 3.3.0 - 5.3.19 + 5.3.20 diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 9d097a630..943172ef9 100755 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 2f52f535c..c74f0be10 100755 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 676db09e3..ab99b7404 100755 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 4bb1c27b4..c3d6548dd 100755 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 7a23f3e9f..5e08bcce0 100755 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-core diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanPath.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanPath.java index ce92e3951..d9e67c99a 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanPath.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanPath.java @@ -1,9 +1,9 @@ package cn.hutool.core.bean; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.collection.ListUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.map.MapUtil; -import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.StrUtil; @@ -11,7 +11,6 @@ import cn.hutool.core.util.StrUtil; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -68,7 +67,7 @@ public class BeanPath implements Serializable{ * @param expression 表达式 * @return BeanPath */ - public static BeanPath create(String expression) { + public static BeanPath create(final String expression) { return new BeanPath(expression); } @@ -77,17 +76,26 @@ public class BeanPath implements Serializable{ * * @param expression 表达式 */ - public BeanPath(String expression) { + public BeanPath(final String expression) { init(expression); } + /** + * 获取表达式解析后的分段列表 + * + * @return 表达式分段列表 + */ + public List getPatternParts(){ + return this.patternParts; + } + /** * 获取Bean中对应表达式的值 * * @param bean Bean对象或Map或List等 * @return 值,如果对应值不存在,则返回null */ - public Object get(Object bean) { + public Object get(final Object bean) { return get(this.patternParts, bean, false); } @@ -104,10 +112,16 @@ public class BeanPath implements Serializable{ * @param bean Bean、Map或List * @param value 值 */ - public void set(Object bean, Object value) { + public void set(final Object bean, final Object value) { set(bean, this.patternParts, value); } + @Override + public String toString() { + return this.patternParts.toString(); + } + + //region Private Methods /** * 设置表达式指定位置(或filed对应)的值
* 若表达式指向一个List则设置其坐标对应位置的值,若指向Map则put对应key的值,Bean则设置字段的值
@@ -122,7 +136,7 @@ public class BeanPath implements Serializable{ * @param patternParts 表达式块列表 * @param value 值 */ - private void set(Object bean, List patternParts, Object value) { + private void set(final Object bean, final List patternParts, final Object value) { Object subBean = get(patternParts, bean, true); if(null == subBean) { set(bean, patternParts.subList(0, patternParts.size() - 1), new HashMap<>()); @@ -132,7 +146,6 @@ public class BeanPath implements Serializable{ BeanUtil.setFieldValue(subBean, patternParts.get(patternParts.size() - 1), value); } - // ------------------------------------------------------------------------------------------------------------------------------------- Private method start /** * 获取Bean中对应表达式的值 * @@ -141,7 +154,7 @@ public class BeanPath implements Serializable{ * @param ignoreLast 是否忽略最后一个值,忽略最后一个值则用于set,否则用于read * @return 值,如果对应值不存在,则返回null */ - private Object get(List patternParts, Object bean, boolean ignoreLast) { + private Object get(final List patternParts, final Object bean, final boolean ignoreLast) { int length = patternParts.size(); if (ignoreLast) { length--; @@ -166,7 +179,7 @@ public class BeanPath implements Serializable{ } @SuppressWarnings("unchecked") - private static Object getFieldValue(Object bean, String expression) { + private static Object getFieldValue(final Object bean, final String expression) { if (StrUtil.isBlank(expression)) { return null; } @@ -174,8 +187,8 @@ public class BeanPath implements Serializable{ if (StrUtil.contains(expression, ':')) { // [start:end:step] 模式 final List parts = StrUtil.splitTrim(expression, ':'); - int start = Integer.parseInt(parts.get(0)); - int end = Integer.parseInt(parts.get(1)); + final int start = Integer.parseInt(parts.get(0)); + final int end = Integer.parseInt(parts.get(1)); int step = 1; if (3 == parts.size()) { step = Integer.parseInt(parts.get(2)); @@ -218,13 +231,14 @@ public class BeanPath implements Serializable{ * * @param expression 表达式 */ - private void init(String expression) { - List localPatternParts = new ArrayList<>(); - int length = expression.length(); + private void init(final String expression) { + final List localPatternParts = new ArrayList<>(); + final int length = expression.length(); - final StrBuilder builder = StrUtil.strBuilder(); + final StringBuilder builder = new StringBuilder(); char c; boolean isNumStart = false;// 下标标识符开始 + boolean isInWrap = false; //标识是否在引号内 for (int i = 0; i < length; i++) { c = expression.charAt(i); if (0 == i && '$' == c) { @@ -233,7 +247,13 @@ public class BeanPath implements Serializable{ continue; } - if (ArrayUtil.contains(EXP_CHARS, c)) { + if('\'' == c){ + // 结束 + isInWrap = (false == isInWrap); + continue; + } + + if (false == isInWrap && ArrayUtil.contains(EXP_CHARS, c)) { // 处理边界符号 if (CharUtil.BRACKET_END == c) { // 中括号(数字下标)结束 @@ -253,9 +273,9 @@ public class BeanPath implements Serializable{ // 每一个边界符之前的表达式是一个完整的KEY,开始处理KEY } if (builder.length() > 0) { - localPatternParts.add(unWrapIfPossible(builder)); + localPatternParts.add(builder.toString()); } - builder.reset(); + builder.setLength(0); } else { // 非边界符号,追加字符 builder.append(c); @@ -267,25 +287,12 @@ public class BeanPath implements Serializable{ throw new IllegalArgumentException(StrUtil.format("Bad expression '{}':{}, we find '[' but no ']' !", expression, length - 1)); } else { if (builder.length() > 0) { - localPatternParts.add(unWrapIfPossible(builder)); + localPatternParts.add(builder.toString()); } } // 不可变List - this.patternParts = Collections.unmodifiableList(localPatternParts); + this.patternParts = ListUtil.unmodifiable(localPatternParts); } - - /** - * 对于非表达式去除单引号 - * - * @param expression 表达式 - * @return 表达式 - */ - private static String unWrapIfPossible(CharSequence expression) { - if (StrUtil.containsAny(expression, " = ", " > ", " < ", " like ", ",")) { - return expression.toString(); - } - return StrUtil.unWrap(expression, '\''); - } - // ------------------------------------------------------------------------------------------------------------------------------------- Private method end + //endregion } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java index 5b8e517c3..84dee2e01 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanUtil.java @@ -616,14 +616,16 @@ public class BeanUtil { * @since 5.8.0 */ public static Map beanToMap(Object bean, String... properties) { + int mapSize = 16; Editor keyEditor = null; if(ArrayUtil.isNotEmpty(properties)){ + mapSize = properties.length; final Set propertiesSet = CollUtil.set(false, properties); keyEditor = property -> propertiesSet.contains(property) ? property : null; } // 指明了要复制的属性 所以不忽略null值 - return beanToMap(bean, new LinkedHashMap<>(properties.length, 1), false, keyEditor); + return beanToMap(bean, new LinkedHashMap<>(mapSize, 1), false, keyEditor); } /** 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 cae324ed4..a764a6c4e 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 @@ -1058,7 +1058,7 @@ public class CollUtil { * @param 集合元素类型 * @param 唯一键类型 * @param collection 集合 - * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 + * @param override 是否覆盖模式,如果为{@code true},加入的新值会覆盖相同key的旧值,否则会忽略新加值 * @return {@link ArrayList} * @since 5.8.0 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/CastUtil.java b/hutool-core/src/main/java/cn/hutool/core/convert/CastUtil.java new file mode 100644 index 000000000..5279bb7e5 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/CastUtil.java @@ -0,0 +1,118 @@ +package cn.hutool.core.convert; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 转换工具类,提供集合、Map等向上向下转换工具 + * + * @author looly + * @since 5.8.1 + */ +public class CastUtil { + /** + * 泛型集合向上转型。例如将Collection<Integer>转换为Collection<Number> + * + * @param collection 集合 + * @param 元素类型 + * @return 转换后的集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Collection castUp(Collection collection) { + return (Collection) collection; + } + + /** + * 泛型集合向下转型。例如将Collection<Number>转换为Collection<Integer> + * + * @param collection 集合 + * @param 元素类型 + * @return 转换后的集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Collection castDown(Collection collection) { + return (Collection) collection; + } + + /** + * 泛型集合向上转型。例如将Set<Integer>转换为Set<Number> + * + * @param set 集合 + * @param 泛型 + * @return 泛化集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Set castUp(Set set) { + return (Set) set; + } + + /** + * 泛型集合向下转型。例如将Set<Number>转换为Set<Integer> + * + * @param set 集合 + * @param 泛型子类 + * @return 泛化集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Set castDown(Set set) { + return (Set) set; + } + + /** + * 泛型接口向上转型。例如将List<Integer>转换为List<Number> + * + * @param list 集合 + * @param 泛型的父类 + * @return 泛化集合 + */ + @SuppressWarnings("unchecked") + public static List castUp(List list) { + return (List) list; + } + + /** + * 泛型集合向下转型。例如将List<Number>转换为List<Integer> + * + * @param list 集合 + * @param 泛型的子类 + * @return 泛化集合 + */ + @SuppressWarnings("unchecked") + public static List castDown(List list) { + return (List) list; + } + + /** + * 泛型集合向下转型。例如将Map<Integer, Integer>转换为Map<Number,Number> + * + * @param map 集合 + * @param 泛型父类 + * @param 泛型父类 + * @return 泛化集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Map castUp(Map map) { + return (Map) map; + } + + /** + * 泛型集合向下转型。例如将Map<Number,Number>转换为Map<Integer, Integer> + * + * @param map 集合 + * @param 泛型子类 + * @param 泛型子类 + * @return 泛化集合 + * @since 5.8.1 + */ + @SuppressWarnings("unchecked") + public static Map castDown(Map map) { + return (Map) map; + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java new file mode 100644 index 000000000..b6444bd54 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/exceptions/InvocationTargetRuntimeException.java @@ -0,0 +1,34 @@ +package cn.hutool.core.exceptions; + +/** + * InvocationTargetException的运行时异常 + * + * @author looly + * @since 5.8.1 + */ +public class InvocationTargetRuntimeException extends UtilException { + + public InvocationTargetRuntimeException(Throwable e) { + super(e); + } + + public InvocationTargetRuntimeException(String message) { + super(message); + } + + public InvocationTargetRuntimeException(String messageTemplate, Object... params) { + super(messageTemplate, params); + } + + public InvocationTargetRuntimeException(String message, Throwable throwable) { + super(message, throwable); + } + + public InvocationTargetRuntimeException(String message, Throwable throwable, boolean enableSuppression, boolean writableStackTrace) { + super(message, throwable, enableSuppression, writableStackTrace); + } + + public InvocationTargetRuntimeException(Throwable throwable, String messageTemplate, Object... params) { + super(throwable, messageTemplate, params); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 90114dc82..5b9b9f3d2 100755 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -1097,7 +1097,7 @@ public class FileUtil extends PathUtil { * 情况如下: * *
-	 * 1、src和dest都为目录,则讲src下所有文件目录拷贝到dest下
+	 * 1、src和dest都为目录,则将src下所有文件目录拷贝到dest下
 	 * 2、src和dest都为文件,直接复制,名字为dest
 	 * 3、src为文件,dest为目录,将src拷贝到dest目录下
 	 * 
@@ -1117,7 +1117,7 @@ public class FileUtil extends PathUtil { * 情况如下: * *
-	 * 1、src和dest都为目录,则讲src下所有文件(包括子目录)拷贝到dest下
+	 * 1、src和dest都为目录,则将src下所有文件(包括子目录)拷贝到dest下
 	 * 2、src和dest都为文件,直接复制,名字为dest
 	 * 3、src为文件,dest为目录,将src拷贝到dest目录下
 	 * 
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 23fb8e604..cc9088143 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 @@ -6,6 +6,7 @@ import cn.hutool.core.lang.Editor; import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Pair; import cn.hutool.core.lang.TypeReference; +import cn.hutool.core.stream.CollectorUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; @@ -27,7 +28,6 @@ import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; import java.util.function.BiFunction; /** @@ -708,7 +708,7 @@ public class MapUtil { if (null == map || null == biFunction) { return MapUtil.newHashMap(); } - return map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, m -> biFunction.apply(m.getKey(), m.getValue()))); + return map.entrySet().stream().collect(CollectorUtil.toMap(Map.Entry::getKey, m -> biFunction.apply(m.getKey(), m.getValue()),(l,r)->l)); } /** @@ -1432,7 +1432,7 @@ public class MapUtil { */ public static Map.Entry entry(K key, V value, boolean isImmutable) { return isImmutable ? - new AbstractMap.SimpleEntry<>(key, value) : - new AbstractMap.SimpleImmutableEntry<>(key, value); + new AbstractMap.SimpleImmutableEntry<>(key, value) : + new AbstractMap.SimpleEntry<>(key, value); } } diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java index 6c7c45382..d38e31ee0 100755 --- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java @@ -780,6 +780,28 @@ public class CharSequenceUtil { return false; } + /** + * 给定字符串是否以任何一个字符串结尾(忽略大小写)
+ * 给定字符串和数组为空都返回false + * + * @param str 给定字符串 + * @param suffixes 需要检测的结尾字符串 + * @return 给定字符串是否以任何一个字符串结尾 + * @since 5.8.1 + */ + public static boolean startWithAnyIgnoreCase(final CharSequence str, final CharSequence... suffixes) { + if (isEmpty(str) || ArrayUtil.isEmpty(suffixes)) { + return false; + } + + for (final CharSequence suffix : suffixes) { + if (startWith(str, suffix, true)) { + return true; + } + } + return false; + } + // ------------------------------------------------------------------------ endWith /** @@ -2707,7 +2729,7 @@ public class CharSequenceUtil { * 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可
* 例:
* 通常使用:format("this is {} for {}", "a", "b") =》 this is a for b
- * 转义{}: format("this is \\{} for {}", "a", "b") =》 this is \{} for a
+ * 转义{}: format("this is \\{} for {}", "a", "b") =》 this is {} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") =》 this is \a for b
* * @param template 文本模板,被替换的部分用 {} 表示,如果模板为null,返回"null" diff --git a/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java index 542f89096..2d215e82b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/BooleanUtil.java @@ -15,6 +15,8 @@ public class BooleanUtil { /** 表示为真的字符串 */ private static final Set TRUE_SET = CollUtil.newHashSet("true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", "對", "√"); + /** 表示为假的字符串 */ + private static final Set FALSE_SET = CollUtil.newHashSet("false", "no", "n", "f", "0", "off", "否", "错", "假", "錯", "×"); /** * 取相反值 @@ -85,6 +87,28 @@ public class BooleanUtil { return false; } + /** + * 转换字符串为boolean值
+ * 如果为["true", "yes", "y", "t", "ok", "1", "on", "是", "对", "真", "對", "√"],返回{@code true}
+ * 如果为["false", "no", "n", "f", "0", "off", "否", "错", "假", "錯", "×"],返回{@code false}
+ * 其他情况返回{@code null} + * + * @param valueStr 字符串 + * @return boolean值 + * @since 5.8.1 + */ + public static Boolean toBooleanObject(String valueStr) { + if (StrUtil.isNotBlank(valueStr)) { + valueStr = valueStr.trim().toLowerCase(); + if(TRUE_SET.contains(valueStr)){ + return true; + } else if(FALSE_SET.contains(valueStr)){ + return false; + } + } + return null; + } + /** * boolean值转为int * diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java index bd1053995..47c50199f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ByteUtil.java @@ -74,12 +74,25 @@ public class ByteUtil { * @param byteOrder 端序 * @return short值 */ - public static short bytesToShort(byte[] bytes, ByteOrder byteOrder) { + public static short bytesToShort(final byte[] bytes, final ByteOrder byteOrder) { + return bytesToShort(bytes, 0, byteOrder); + } + + /** + * byte数组转short
+ * 自定义端序 + * + * @param bytes byte数组,长度必须大于2 + * @param start 开始位置 + * @param byteOrder 端序 + * @return short值 + */ + public static short bytesToShort(final byte[] bytes, final int start, final ByteOrder byteOrder) { if (ByteOrder.LITTLE_ENDIAN == byteOrder) { //小端模式,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中 - return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE); + return (short) (bytes[start] & 0xff | (bytes[start + 1] & 0xff) << Byte.SIZE); } else { - return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE); + return (short) (bytes[start + 1] & 0xff | (bytes[start] & 0xff) << Byte.SIZE); } } 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 3deccb27a..5b40c361f 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 @@ -2524,6 +2524,11 @@ public class NumberUtil { * @since 4.1.15 */ public static Number parseNumber(String numberStr) throws NumberFormatException { + if(StrUtil.startWithIgnoreCase(numberStr, "0x")){ + // 0x04表示16进制数 + return Long.parseLong(numberStr.substring(2), 16); + } + try { final NumberFormat format = NumberFormat.getInstance(); if (format instanceof DecimalFormat) { 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 39d94196e..7a4c741d4 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 @@ -5,6 +5,7 @@ import cn.hutool.core.bean.NullWrapperBean; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.UniqueKeySet; import cn.hutool.core.convert.Convert; +import cn.hutool.core.exceptions.InvocationTargetRuntimeException; import cn.hutool.core.exceptions.UtilException; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Filter; @@ -16,6 +17,7 @@ import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.AbstractMap; import java.util.ArrayList; @@ -864,7 +866,7 @@ public class ReflectUtil { * Set -》 HashSet * * - * @param 对象类型 + * @param 对象类型 * @param type 被构造的类 * @return 构造后的对象,构造失败返回{@code null} */ @@ -873,7 +875,7 @@ public class ReflectUtil { Assert.notNull(type); // 原始类型 - if(type.isPrimitive()){ + if (type.isPrimitive()) { return (T) ClassUtil.getPrimitiveDefaultValue(type); } @@ -985,10 +987,42 @@ public class ReflectUtil { * @param method 方法(对象方法或static方法都可) * @param args 参数对象 * @return 结果 - * @throws UtilException 一些列异常的包装 + * @throws InvocationTargetRuntimeException 目标方法执行异常 + * @throws UtilException {@link IllegalAccessException}异常的包装 + */ + public static T invoke(Object obj, Method method, Object... args) throws InvocationTargetRuntimeException, UtilException { + try { + return invokeRaw(obj, method, args); + } catch (InvocationTargetException e) { + throw new InvocationTargetRuntimeException(e); + } catch (IllegalAccessException e) { + throw new UtilException(e); + } + } + + /** + * 执行方法 + * + *

+ * 对于用户传入参数会做必要检查,包括: + * + *

+	 *     1、忽略多余的参数
+	 *     2、参数不够补齐默认值
+	 *     3、传入参数为null,但是目标参数类型为原始类型,做转换
+	 * 
+ * + * @param 返回对象类型 + * @param obj 对象,如果执行静态方法,此值为{@code null} + * @param method 方法(对象方法或static方法都可) + * @param args 参数对象 + * @return 结果 + * @throws InvocationTargetRuntimeException 目标方法执行异常 + * @throws UtilException {@link IllegalAccessException}异常的包装 + * @since 5.8.1 */ @SuppressWarnings("unchecked") - public static T invoke(Object obj, Method method, Object... args) throws UtilException { + public static T invokeRaw(Object obj, Method method, Object... args) throws InvocationTargetException, IllegalAccessException { setAccessible(method); // 检查用户传入参数: @@ -1025,11 +1059,7 @@ public class ReflectUtil { return MethodHandleUtil.invokeSpecial(obj, method, args); } - try { - return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs); - } catch (Exception e) { - throw new UtilException(e); - } + return (T) method.invoke(ClassUtil.isStatic(method) ? null : obj, actualArgs); } /** @@ -1041,7 +1071,7 @@ public class ReflectUtil { * @param methodName 方法名 * @param args 参数列表 * @return 执行结果 - * @throws UtilException IllegalAccessException包装 + * @throws UtilException IllegalAccessException等异常包装 * @see NullWrapperBean * @since 3.1.2 */ 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 89de82f85..60f602fe0 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 @@ -191,6 +191,23 @@ public class BeanUtilTest { Assert.assertFalse(map.containsKey("SUBNAME")); } + @Test + public void beanToMapNullPropertiesTest() { + SubPerson person = new SubPerson(); + person.setAge(14); + person.setOpenid("11213232"); + person.setName("测试A11"); + person.setSubName("sub名字"); + + Map map = BeanUtil.beanToMap(person, null); + + Assert.assertEquals("测试A11", map.get("name")); + Assert.assertEquals(14, map.get("age")); + Assert.assertEquals("11213232", map.get("openid")); + // static属性应被忽略 + Assert.assertFalse(map.containsKey("SUBNAME")); + } + @Test public void beanToMapTest2() { SubPerson person = new SubPerson(); diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/CastUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/CastUtilTest.java new file mode 100644 index 000000000..16e9e01ee --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/convert/CastUtilTest.java @@ -0,0 +1,45 @@ +package cn.hutool.core.convert; + +import cn.hutool.core.collection.CollUtil; +import org.junit.Assert; +import org.junit.Test; + +import java.io.Serializable; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class CastUtilTest { + + @Test + public void testCastToSuper() { + Collection collection= CollUtil.newLinkedList(1,2,3); + List list = CollUtil.newArrayList(1, 2, 3); + Set set = CollUtil.newHashSet(1, 2, 3); + Map map = new HashMap<>(); + map.put(1, 1); + + Collection collection2 = CastUtil.castUp(collection); + Assert.assertSame(collection, collection2); + + Collection collection3 = CastUtil.castDown(collection2); + Assert.assertSame(collection2, collection3); + + List list2 = CastUtil.castUp(list); + Assert.assertSame(list, list2); + List list3 = CastUtil.castDown(list2); + Assert.assertSame(list2, list3); + + Set set2 = CastUtil.castUp(set); + Assert.assertSame(set, set2); + Set set3 = CastUtil.castDown(set2); + Assert.assertSame(set2, set3); + + Map map2 = CastUtil.castUp(map); + Assert.assertSame(map, map2); + Map map3 = CastUtil.castDown(map2); + Assert.assertSame(map2, map3); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java index 876e31446..aa667dc45 100644 --- a/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/map/MapUtilTest.java @@ -82,7 +82,8 @@ public class MapUtilTest { // 如你所见,它是一个map,key由用户id,value由用户组成 Map idUserMap = Stream.iterate(0L, i -> ++i).limit(4).map(i -> User.builder().id(i).name(customers.poll()).build()).collect(Collectors.toMap(User::getId, Function.identity())); // 如你所见,它是一个map,key由分组id,value由用户ids组成,典型的多对多关系 - Map> groupIdUserIdsMap = groups.stream().flatMap(group -> idUserMap.keySet().stream().map(userId -> UserGroup.builder().groupId(group.getId()).userId(userId).build())).collect(Collectors.groupingBy(UserGroup::getUserId, Collectors.mapping(UserGroup::getGroupId, Collectors.toList()))); + Map> groupIdUserIdsMap = groups.stream().flatMap(group -> idUserMap.keySet().stream().map(userId -> UserGroup.builder().groupId(group.getId()).userId(userId).build())) + .collect(Collectors.groupingBy(UserGroup::getGroupId, Collectors.mapping(UserGroup::getUserId, Collectors.toList()))); // 神奇的魔法发生了, 分组id和用户ids组成的map,竟然变成了订单编号和用户实体集合组成的map Map> groupIdUserMap = MapUtil.map(groupIdUserIdsMap, (groupId, userIds) -> userIds.stream().map(idUserMap::get).collect(Collectors.toList())); @@ -98,7 +99,8 @@ public class MapUtilTest { Assert.assertEquals("竹鼠发烧找华农", users.get(2).getName()); Assert.assertEquals("朴实无华朱一旦", users.get(3).getName()); }); - // 能写代码真开心 + // 对null友好 + MapUtil.map(MapUtil.of(0, 0), (k, v) -> null).forEach((k, v) -> Assert.assertNull(v)); } @Test diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 489a3faf8..f3a8e4859 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -292,6 +292,13 @@ public class NumberUtilTest { Assert.assertEquals(1482L, v2.longValue()); } + @Test + public void parseHexNumberTest() { + // 千位分隔符去掉 + final int v1 = NumberUtil.parseNumber("0xff").intValue(); + Assert.assertEquals(255, v1); + } + @Test public void parseLongTest() { long number = NumberUtil.parseLong("0xFF"); diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index b2139d0e6..02d3d1493 100755 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 8c967bffb..5723a93b5 100755 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 6b3188371..44776cba6 100755 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-db @@ -81,7 +81,7 @@ com.github.chris2018998 beecp - 3.3.5 + 3.3.6 slf4j-api diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java index 8e3d978b9..eeeb1c7da 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/DialectName.java @@ -9,7 +9,7 @@ import cn.hutool.core.util.StrUtil; * @author Looly */ public enum DialectName { - ANSI, MYSQL, ORACLE, POSTGREESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX; + ANSI, MYSQL, ORACLE, POSTGRESQL, SQLITE3, H2, SQLSERVER, SQLSERVER2012, PHOENIX; /** * 是否为指定数据库方言,检查时不分区大小写 diff --git a/hutool-db/src/main/java/cn/hutool/db/dialect/impl/PostgresqlDialect.java b/hutool-db/src/main/java/cn/hutool/db/dialect/impl/PostgresqlDialect.java index 1f5a90122..0a5e0fc7d 100644 --- a/hutool-db/src/main/java/cn/hutool/db/dialect/impl/PostgresqlDialect.java +++ b/hutool-db/src/main/java/cn/hutool/db/dialect/impl/PostgresqlDialect.java @@ -28,7 +28,7 @@ public class PostgresqlDialect extends AnsiSqlDialect{ @Override public String dialectName() { - return DialectName.POSTGREESQL.name(); + return DialectName.POSTGRESQL.name(); } @Override diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index bb5c1b43c..7fb33051d 100755 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index fe6e30d38..f8f9315ec 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index da31f1d78..6a9c1b045 100755 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 0d0d1152c..a87d5ac09 100755 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-json diff --git a/hutool-jwt/pom.xml b/hutool-jwt/pom.xml index 5b80df24c..dbf7ca3f9 100755 --- a/hutool-jwt/pom.xml +++ b/hutool-jwt/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-jwt diff --git a/hutool-jwt/src/main/java/cn/hutool/jwt/JWTValidator.java b/hutool-jwt/src/main/java/cn/hutool/jwt/JWTValidator.java index 77f7c2591..fc5d97210 100755 --- a/hutool-jwt/src/main/java/cn/hutool/jwt/JWTValidator.java +++ b/hutool-jwt/src/main/java/cn/hutool/jwt/JWTValidator.java @@ -222,7 +222,9 @@ public class JWTValidator { if (null == dateToCheck) { return; } - now.setTime(now.getTime() + leeway * 1000); + if(leeway > 0){ + now = DateUtil.date(now.getTime() + leeway * 1000); + } if (dateToCheck.after(now)) { throw new ValidateException("'{}':[{}] is after now:[{}]", fieldName, DateUtil.date(dateToCheck), DateUtil.date(now)); @@ -244,7 +246,9 @@ public class JWTValidator { if (null == dateToCheck) { return; } - now.setTime(now.getTime() - leeway * 1000); + if(leeway > 0){ + now = DateUtil.date(now.getTime() - leeway * 1000); + } if (dateToCheck.before(now)) { throw new ValidateException("'{}':[{}] is before now:[{}]", fieldName, DateUtil.date(dateToCheck), DateUtil.date(now)); diff --git a/hutool-jwt/src/test/java/cn/hutool/jwt/JWTValidatorTest.java b/hutool-jwt/src/test/java/cn/hutool/jwt/JWTValidatorTest.java index b3df4faff..15365eeaf 100755 --- a/hutool-jwt/src/test/java/cn/hutool/jwt/JWTValidatorTest.java +++ b/hutool-jwt/src/test/java/cn/hutool/jwt/JWTValidatorTest.java @@ -6,6 +6,8 @@ import cn.hutool.jwt.signers.JWTSignerUtil; import org.junit.Assert; import org.junit.Test; +import java.util.Date; + public class JWTValidatorTest { @Test(expected = ValidateException.class) @@ -79,4 +81,20 @@ public class JWTValidatorTest { JWTValidator.of(jwt).validateDate(DateUtil.date()); } + + @Test + public void issue2329Test(){ + final long NOW = System.currentTimeMillis(); + final Date NOW_TIME = new Date(NOW); + final long EXPIRED = 3 * 1000L; + final Date EXPIRED_TIME = new Date(NOW + EXPIRED); + + // 使用这种方式生成token + final String token = JWT.create().setPayload("sub", "blue-light").setIssuedAt(NOW_TIME).setNotBefore(EXPIRED_TIME) + .setExpiresAt(EXPIRED_TIME).setKey("123456".getBytes()).sign(); + + // 使用这种方式验证token + JWTValidator.of(JWT.of(token)).validateDate(DateUtil.date(NOW - 4000), 10); + JWTValidator.of(JWT.of(token)).validateDate(DateUtil.date(NOW + 4000), 10); + } } diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 36a5fc35d..48dbfc344 100755 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-log @@ -24,6 +24,7 @@ 2.17.2 1.2 1.3.6 + 3.4.3.Final 0.43.2 diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 43bcd8e7c..2940278bb 100755 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-poi @@ -45,7 +45,7 @@ org.ofdrw ofdrw-full - 1.17.14 + 1.17.15 compile true diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index ada7ffeaa..d01af5420 100755 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 2a366d0b6..655a3a1e8 100755 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 8b74e2c32..b700c75a4 100755 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 2a8c2e164..cea4cd544 100755 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool-system diff --git a/hutool-system/src/main/java/cn/hutool/system/JavaInfo.java b/hutool-system/src/main/java/cn/hutool/system/JavaInfo.java index 256cfdee2..34a91e38a 100755 --- a/hutool-system/src/main/java/cn/hutool/system/JavaInfo.java +++ b/hutool-system/src/main/java/cn/hutool/system/JavaInfo.java @@ -30,14 +30,21 @@ public class JavaInfo implements Serializable { private final boolean IS_JAVA_10 = getJavaVersionMatches("10"); private final boolean IS_JAVA_11 = getJavaVersionMatches("11"); private final boolean IS_JAVA_12 = getJavaVersionMatches("12"); + private final boolean IS_JAVA_13 = getJavaVersionMatches("13"); + private final boolean IS_JAVA_14 = getJavaVersionMatches("14"); + private final boolean IS_JAVA_15 = getJavaVersionMatches("15"); + private final boolean IS_JAVA_16 = getJavaVersionMatches("16"); + private final boolean IS_JAVA_17 = getJavaVersionMatches("17"); + private final boolean IS_JAVA_18 = getJavaVersionMatches("18"); + /** - * 取得当前Java impl.的版本(取自系统属性:java.version)。 + * 取得当前Java impl.的版本(取自系统属性:{@code java.version})。 * *

- * 例如Sun JDK 1.4.2:"1.4.2" + * 例如Sun JDK 1.4.2:{@code "1.4.2"} * - * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回null。 + * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回{@code null}。 * @since Java 1.1 */ public final String getVersion() { @@ -45,35 +52,35 @@ public class JavaInfo implements Serializable { } /** - * 取得当前Java impl.的版本(取自系统属性:java.version)。 + * 取得当前Java impl.的版本(取自系统属性:{@code java.version})。 * *

* 例如: * *

    - *
  • JDK 1.2:1.2f
  • - *
  • JDK 1.3.1:1.31f
  • + *
  • JDK 1.2:{@code 1.2f}。
  • + *
  • JDK 1.3.1:{@code 1.31f}
  • *
* - * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回0。 + * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回{@code 0}。 */ public final float getVersionFloat() { return JAVA_VERSION_FLOAT; } /** - * 取得当前Java impl.的版本(取自系统属性:java.version),java10及其之后的版本返回值为4位。 + * 取得当前Java impl.的版本(取自系统属性:{@code java.version}),java10及其之后的版本返回值为4位。 * *

* 例如: * *

    - *
  • JDK 1.2:120
  • - *
  • JDK 1.3.1:131
  • - *
  • JDK 11.0.2:1102
  • + *
  • JDK 1.2:{@code 120}。
  • + *
  • JDK 1.3.1:{@code 131}
  • + *
  • JDK 11.0.2:{@code 1102}
  • *
* - * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回0。 + * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回{@code 0}。 * @since Java 1.1 */ public final int getVersionInt() { @@ -81,9 +88,9 @@ public class JavaInfo implements Serializable { } /** - * 取得当前Java impl.的版本的float值。 + * 取得当前Java impl.的版本的{@code float}值。 * - * @return Java版本的float值或0 + * @return Java版本的float值或{@code 0} */ private float getJavaVersionAsFloat() { if (JAVA_VERSION == null) { @@ -98,18 +105,18 @@ public class JavaInfo implements Serializable { } /** - * 取得当前Java impl.的版本的int值。 + * 取得当前Java impl.的版本的{@code int}值。 * - * @return Java版本的int值或0 + * @return Java版本的int值或{@code 0} */ private int getJavaVersionAsInt() { if (JAVA_VERSION == null) { return 0; } - String javaVersion = ReUtil.get("^[0-9]{1,2}(\\.[0-9]{1,2}){0,2}", JAVA_VERSION, 0); + final String javaVersion = ReUtil.get("^[0-9]{1,2}(\\.[0-9]{1,2}){0,2}", JAVA_VERSION, 0); - String[] split = javaVersion.split("\\."); + final String[] split = javaVersion.split("\\."); String result = ArrayUtil.join(split, ""); //保证java10及其之后的版本返回的值为4位 @@ -121,12 +128,12 @@ public class JavaInfo implements Serializable { } /** - * 取得当前Java impl.的厂商(取自系统属性:java.vendor)。 + * 取得当前Java impl.的厂商(取自系统属性:{@code java.vendor})。 * *

- * 例如Sun JDK 1.4.2:"Sun Microsystems Inc." + * 例如Sun JDK 1.4.2:{@code "Sun Microsystems Inc."} * - * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回null。 + * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回{@code null}。 * @since Java 1.1 */ public final String getVendor() { @@ -134,12 +141,12 @@ public class JavaInfo implements Serializable { } /** - * 取得当前Java impl.的厂商网站的URL(取自系统属性:java.vendor.url)。 + * 取得当前Java impl.的厂商网站的URL(取自系统属性:{@code java.vendor.url})。 * *

- * 例如Sun JDK 1.4.2:"http://java.sun.com/" + * 例如Sun JDK 1.4.2:{@code "http://java.sun.com/"} * - * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回null。 + * @return 属性值,如果不能取得(因为Java安全限制)或值不存在,则返回{@code null}。 * @since Java 1.1 */ public final String getVendorURL() { @@ -150,9 +157,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.1,则返回true + * @return 如果当前Java版本为1.1,则返回{@code true} */ public final boolean isJava1_1() { return IS_JAVA_1_1; @@ -162,9 +169,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.2,则返回true + * @return 如果当前Java版本为1.2,则返回{@code true} */ public final boolean isJava1_2() { return IS_JAVA_1_2; @@ -174,9 +181,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.3,则返回true + * @return 如果当前Java版本为1.3,则返回{@code true} */ public final boolean isJava1_3() { return IS_JAVA_1_3; @@ -186,9 +193,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.4,则返回true + * @return 如果当前Java版本为1.4,则返回{@code true} */ public final boolean isJava1_4() { return IS_JAVA_1_4; @@ -198,9 +205,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.5,则返回true + * @return 如果当前Java版本为1.5,则返回{@code true} */ public final boolean isJava1_5() { return IS_JAVA_1_5; @@ -210,9 +217,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.6,则返回true + * @return 如果当前Java版本为1.6,则返回{@code true} */ public final boolean isJava1_6() { return IS_JAVA_1_6; @@ -222,9 +229,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.7,则返回true + * @return 如果当前Java版本为1.7,则返回{@code true} */ public final boolean isJava1_7() { return IS_JAVA_1_7; @@ -234,9 +241,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为1.8,则返回true + * @return 如果当前Java版本为1.8,则返回{@code true} */ public final boolean isJava1_8() { return IS_JAVA_1_8; @@ -246,9 +253,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为9,则返回true + * @return 如果当前Java版本为9,则返回{@code true} */ public final boolean isJava9() { return IS_JAVA_9; @@ -258,9 +265,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为10,则返回true + * @return 如果当前Java版本为10,则返回{@code true} */ public final boolean isJava10() { return IS_JAVA_10; @@ -270,9 +277,9 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为11,则返回true + * @return 如果当前Java版本为11,则返回{@code true} */ public final boolean isJava11() { return IS_JAVA_11; @@ -282,21 +289,94 @@ public class JavaInfo implements Serializable { * 判断当前Java的版本。 * *

- * 如果不能取得系统属性java.version(因为Java安全限制),则总是返回 false + * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} * - * @return 如果当前Java版本为12,则返回true + * @return 如果当前Java版本为12,则返回{@code true} */ public final boolean isJava12() { return IS_JAVA_12; } + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为13,则返回{@code true} + */ + public final boolean isJava13() { + return IS_JAVA_13; + } + + + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为14,则返回{@code true} + */ + public final boolean isJava14() { + return IS_JAVA_14; + } + + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为15,则返回{@code true} + */ + public final boolean isJava15() { + return IS_JAVA_15; + } + + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为16,则返回{@code true} + */ + public final boolean isJava16() { + return IS_JAVA_16; + } + + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为17,则返回{@code true} + */ + public final boolean isJava17() { + return IS_JAVA_17; + } + + /** + * 判断当前Java的版本。 + * + *

+ * 如果不能取得系统属性{@code java.version}(因为Java安全限制),则总是返回 {@code false} + * + * @return 如果当前Java版本为18,则返回{@code true} + */ + public final boolean isJava18() { + return IS_JAVA_18; + } + /** * 匹配当前Java的版本。 * * @param versionPrefix Java版本前缀 - * @return 如果版本匹配,则返回true + * @return 如果版本匹配,则返回{@code true} */ - private boolean getJavaVersionMatches(String versionPrefix) { + private boolean getJavaVersionMatches(final String versionPrefix) { if (JAVA_VERSION == null) { return false; } @@ -312,14 +392,14 @@ public class JavaInfo implements Serializable { * * *

    - *
  • 测试JDK 1.2:isJavaVersionAtLeast(1.2f)
  • - *
  • 测试JDK 1.2.1:isJavaVersionAtLeast(1.31f)
  • + *
  • 测试JDK 1.2:{@code isJavaVersionAtLeast(1.2f)}
  • + *
  • 测试JDK 1.2.1:{@code isJavaVersionAtLeast(1.31f)}
  • *
* * @param requiredVersion 需要的版本 - * @return 如果当前Java版本大于或等于指定的版本,则返回true + * @return 如果当前Java版本大于或等于指定的版本,则返回{@code true} */ - public final boolean isJavaVersionAtLeast(float requiredVersion) { + public final boolean isJavaVersionAtLeast(final float requiredVersion) { return getVersionFloat() >= requiredVersion; } @@ -331,14 +411,14 @@ public class JavaInfo implements Serializable { * * *
    - *
  • 测试JDK 1.2:isJavaVersionAtLeast(120)
  • - *
  • 测试JDK 1.2.1:isJavaVersionAtLeast(131)
  • + *
  • 测试JDK 1.2:{@code isJavaVersionAtLeast(120)}
  • + *
  • 测试JDK 1.2.1:{@code isJavaVersionAtLeast(131)}
  • *
* * @param requiredVersion 需要的版本 - * @return 如果当前Java版本大于或等于指定的版本,则返回true + * @return 如果当前Java版本大于或等于指定的版本,则返回{@code true} */ - public final boolean isJavaVersionAtLeast(int requiredVersion) { + public final boolean isJavaVersionAtLeast(final int requiredVersion) { return getVersionInt() >= requiredVersion; } @@ -349,7 +429,7 @@ public class JavaInfo implements Serializable { */ @Override public final String toString() { - StringBuilder builder = new StringBuilder(); + final StringBuilder builder = new StringBuilder(); SystemUtil.append(builder, "Java Version: ", getVersion()); SystemUtil.append(builder, "Java Vendor: ", getVendor()); diff --git a/pom.xml b/pom.xml index d874dbd2e..ba4a3b432 100755 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.8.0 + 5.8.1 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/dromara/hutool