This commit is contained in:
Looly 2023-04-22 21:53:58 +08:00
parent 2d9febc7fb
commit 6a04ef4a3a
12 changed files with 422 additions and 299 deletions

View File

@ -95,10 +95,7 @@ public class LambdaFactory {
ReflectUtil.setAccessible(executable);
// 获取Lambda函数
final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract);
Assert.equals(abstractMethods.length, 1, "不支持非函数式接口");
final Method invokeMethod = abstractMethods[0];
final Method invokeMethod = LambdaUtil.getInvokeMethod(funcType);
try {
return (F) metaFactory(funcType, invokeMethod, executable)
.getTarget().invoke();
@ -110,20 +107,24 @@ public class LambdaFactory {
/**
* 通过Lambda函数代理方法或构造
*
* @param funcType 函数类型
* @param invokeMethod 函数执行的方法
* @param executable 被代理的方法或构造
* @param funcType 函数类型
* @param funcMethod 函数执行的方法
* @param executable 被代理的方法或构造
* @return {@link CallSite}
* @throws LambdaConversionException 权限等异常
*/
private static CallSite metaFactory(final Class<?> funcType, final Method invokeMethod,
private static CallSite metaFactory(final Class<?> funcType, final Method funcMethod,
final Executable executable) throws LambdaConversionException {
// 查找上下文与调用者的访问权限
final MethodHandles.Lookup caller = LookupUtil.lookup(executable.getDeclaringClass());
final String invokeName = invokeMethod.getName();
// 要实现的方法的名字
final String invokeName = funcMethod.getName();
// 调用点期望的方法参数的类型和返回值的类型(方法signature)
final MethodType invokedType = MethodType.methodType(funcType);
final Class<?>[] paramTypes = invokeMethod.getParameterTypes();
final MethodType samMethodType = MethodType.methodType(invokeMethod.getReturnType(), paramTypes);
final Class<?>[] paramTypes = funcMethod.getParameterTypes();
// 函数对象将要实现的接口方法类型
final MethodType samMethodType = MethodType.methodType(funcMethod.getReturnType(), paramTypes);
if (ClassUtil.isSerializable(funcType)) {
return LambdaMetafactory.altMetafactory(

View File

@ -15,9 +15,11 @@ package org.dromara.hutool.core.func;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.exceptions.HutoolException;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.lang.Opt;
import org.dromara.hutool.core.map.WeakConcurrentMap;
import org.dromara.hutool.core.reflect.MethodUtil;
import org.dromara.hutool.core.reflect.ModifierUtil;
import org.dromara.hutool.core.reflect.ReflectUtil;
import java.io.Serializable;
@ -76,9 +78,9 @@ public class LambdaUtil {
public static <R, T extends Serializable> Class<R> getRealClass(final T func) {
final LambdaInfo lambdaInfo = resolve(func);
return (Class<R>) Opt.of(lambdaInfo)
.map(LambdaInfo::getInstantiatedMethodParameterTypes)
.filter(types -> types.length != 0).map(types -> types[types.length - 1])
.orElseGet(lambdaInfo::getClazz);
.map(LambdaInfo::getInstantiatedMethodParameterTypes)
.filter(types -> types.length != 0).map(types -> types[types.length - 1])
.orElseGet(lambdaInfo::getClazz);
}
/**
@ -104,7 +106,7 @@ public class LambdaUtil {
final Method[] methods = MethodUtil.getMethods(implClass);
for (final Method method : methods) {
if (method.getName().equals(methodName)
&& ReflectUtil.getDescriptor(method).equals(serializedLambda.getImplMethodSignature())) {
&& ReflectUtil.getDescriptor(method).equals(serializedLambda.getImplMethodSignature())) {
return new LambdaInfo(method, serializedLambda);
}
}
@ -181,7 +183,7 @@ public class LambdaUtil {
@SuppressWarnings("unchecked")
public static <T, P> BiConsumer<T, P> buildSetter(final Method setMethod) {
final Class<?> returnType = setMethod.getReturnType();
if(Void.TYPE == returnType){
if (Void.TYPE == returnType) {
return LambdaFactory.build(BiConsumer.class, setMethod);
}
@ -261,7 +263,22 @@ public class LambdaUtil {
return (t) -> biConsumer.accept(t, param);
}
//region Private methods
/**
* 获取函数的执行方法
*
* @param funcType 函数接口类
* @return {@link Method}
* @since 6.0.0
*/
public static Method getInvokeMethod(final Class<?> funcType) {
// 获取Lambda函数
final Method[] abstractMethods = MethodUtil.getPublicMethods(funcType, ModifierUtil::isAbstract);
Assert.equals(abstractMethods.length, 1, "Not a function class: " + funcType.getName());
return abstractMethods[0];
}
//region ----- Private methods
/**
* 解析lambda表达式,没加缓存

View File

@ -14,6 +14,7 @@ package org.dromara.hutool.core.math;
import org.dromara.hutool.core.text.StrUtil;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
@ -205,6 +206,47 @@ public class NumberParser {
}
}
/**
* 解析为{@link BigInteger}支持16进制10进制和8进制如果传入空白串返回null<br>
* from Apache Common Lang
*
* @param str 数字字符串
* @return {@link BigInteger}
*/
public BigInteger parseBigInteger(String str) {
str = StrUtil.trimToNull(str);
if (null == str) {
return null;
}
int pos = 0; // 数字字符串位置
int radix = 10;
boolean negate = false; // 负数与否
if (str.startsWith("-")) {
negate = true;
pos = 1;
}
if (str.startsWith("0x", pos) || str.startsWith("0X", pos)) {
// hex
radix = 16;
pos += 2;
} else if (str.startsWith("#", pos)) {
// alternative hex (allowed by Long/Integer)
radix = 16;
pos++;
} else if (str.startsWith("0", pos) && str.length() > pos + 1) {
// octal; so long as there are additional digits
radix = 8;
pos++;
} // default is to treat as decimal
if (pos > 0) {
str = str.substring(pos);
}
final BigInteger value = new BigInteger(str, radix);
return negate ? value.negate() : value;
}
/**
* 将指定字符串转换为{@link Number} 对象<br>
* 此方法不支持科学计数法

View File

@ -16,7 +16,6 @@ import org.dromara.hutool.core.array.ArrayUtil;
import org.dromara.hutool.core.comparator.CompareUtil;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharUtil;
import org.dromara.hutool.core.util.ObjUtil;
import java.math.BigDecimal;
@ -50,7 +49,7 @@ import java.util.Objects;
*
* @author Looly
*/
public class NumberUtil {
public class NumberUtil extends NumberValidator {
/**
* 默认除法运算精度
@ -641,233 +640,6 @@ public class NumberUtil {
}
// endregion
// region ----- isXXX
/**
* 是否为数字支持包括
*
* <pre>
* 110进制
* 216进制数字0x开头
* 3科学计数法形式1234E3
* 4类型标识形式123D
* 5正负数标识形式+123-234
* 6八进制数字(0开头)
* </pre>
*
* @param str 字符串值, 不可以含有任何空白字符
* @return 是否为数字
*/
public static boolean isNumber(final CharSequence str) {
if (StrUtil.isBlank(str)) {
return false;
}
final char[] chars = str.toString().toCharArray();
int sz = chars.length;
boolean hasExp = false;
boolean hasDecPoint = false;
boolean allowSigns = false;
boolean foundDigit = false;
// deal with any possible sign up front
final int start = (chars[0] == '-' || chars[0] == '+') ? 1 : 0;
if (sz > start + 1 && chars[start] == '0' && !StrUtil.contains(str, CharUtil.DOT)) { // leading 0, skip if is a decimal number
if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X
int i = start + 2;
if (i == sz) {
return false; // str == "0x"
}
// checking hex (it can't be anything else)
for (; i < chars.length; i++) {
if ((chars[i] < '0' || chars[i] > '9') && (chars[i] < 'a' || chars[i] > 'f') && (chars[i] < 'A' || chars[i] > 'F')) {
return false;
}
}
return true;
}
if (Character.isDigit(chars[start + 1])) {
// leading 0, but not hex, must be octal
int i = start + 1;
for (; i < chars.length; i++) {
if (chars[i] < '0' || chars[i] > '7') {
return false;
}
}
return true;
}
}
sz--; // don't want to loop to the last char, check it afterwords
// for type qualifiers
int i = start;
// loop to the next to last char or to the last char if we need another digit to
// make a valid number (e.g. chars[0..5] = "1234E")
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
if (chars[i] >= '0' && chars[i] <= '9') {
foundDigit = true;
allowSigns = false;
} else if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
hasDecPoint = true;
} else if (chars[i] == 'e' || chars[i] == 'E') {
// we've already taken care of hex.
if (hasExp) {
// two E's
return false;
}
if (!foundDigit) {
return false;
}
hasExp = true;
allowSigns = true;
} else if (chars[i] == '+' || chars[i] == '-') {
if (!allowSigns) {
return false;
}
allowSigns = false;
foundDigit = false; // we need a digit after the E
} else {
return false;
}
i++;
}
if (i < chars.length) {
if (chars[i] >= '0' && chars[i] <= '9') {
// no type qualifier, OK
return true;
}
if (chars[i] == 'e' || chars[i] == 'E') {
// can't have an E at the last byte
return false;
}
if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
// single trailing decimal point after non-exponent is ok
return foundDigit;
}
if (!allowSigns && (chars[i] == 'd' || chars[i] == 'D' || chars[i] == 'f' || chars[i] == 'F')) {
return foundDigit;
}
if (chars[i] == 'l' || chars[i] == 'L') {
// not allowing L with an exponent or decimal point
return foundDigit && !hasExp && !hasDecPoint;
}
// last character is illegal
return false;
}
// allowSigns is true iff the val ends in 'E'
// found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
return !allowSigns && foundDigit;
}
/**
* 判断字符串是否是整数
*
* <p>支持格式:
* <ol>
* <li>10进制, 不能包含前导零</li>
* <li>8进制(以0开头)</li>
* <li>16进制(以0x或者0X开头)</li>
* </ol>
*
* @param s 校验的字符串, 只能含有 正负号数字字符 {@literal X/x}
* @return 是否为 {@link Integer}类型
* @apiNote 6.0.0 支持8进制和16进制
* @see Integer#decode(String)
*/
public static boolean isInteger(final String s) {
if (!isNumber(s)) {
return false;
}
try {
//noinspection ResultOfMethodCallIgnored
Integer.decode(s);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是Long类型<br>
*
* <p>支持格式:
* <ol>
* <li>10进制, 不能包含前导零</li>
* <li>8进制(以0开头)</li>
* <li>16进制(以0x或者0X开头)</li>
* </ol>
*
* @param s 校验的字符串, 只能含有 正负号数字字符{@literal X/x} 后缀{@literal L/l}
* @return 是否为 {@link Long}类型
* @apiNote 6.0.0 支持8进制和16进制数字
* @since 4.0.0
*/
public static boolean isLong(final String s) {
if (!isNumber(s)) {
return false;
}
final char lastChar = s.charAt(s.length() - 1);
if (lastChar == 'l' || lastChar == 'L') {
return true;
}
try {
//noinspection ResultOfMethodCallIgnored
Long.decode(s);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是浮点数
*
* @param s String
* @return 是否为 {@link Double}类型
*/
public static boolean isDouble(final String s) {
if (StrUtil.isBlank(s)) {
return false;
}
try {
Double.parseDouble(s);
} catch (final NumberFormatException ignore) {
return false;
}
return s.contains(".");
}
/**
* 是否是质数素数<br>
* 质数表的质数又称素数指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数
*
* @param n 数字
* @return 是否是质数
*/
public static boolean isPrime(final int n) {
Assert.isTrue(n > 1, "The number must be > 1");
if (n <= 3) {
return true;
} else if ((n & 1) == 0) {
// 快速排除偶数
return false;
}
final int end = (int) Math.sqrt(n);
for (int i = 3; i <= end; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
// endregion
// region ----- range
/**
@ -1252,42 +1024,12 @@ public class NumberUtil {
* 创建{@link BigInteger}支持16进制10进制和8进制如果传入空白串返回null<br>
* from Apache Common Lang
*
* @param str 数字字符串
* @param numberStr 数字字符串
* @return {@link BigInteger}
* @since 3.2.1
* @since 6.0.0
*/
public static BigInteger newBigInteger(String str) {
str = StrUtil.trimToNull(str);
if (null == str) {
return null;
}
int pos = 0; // 数字字符串位置
int radix = 10;
boolean negate = false; // 负数与否
if (str.startsWith("-")) {
negate = true;
pos = 1;
}
if (str.startsWith("0x", pos) || str.startsWith("0X", pos)) {
// hex
radix = 16;
pos += 2;
} else if (str.startsWith("#", pos)) {
// alternative hex (allowed by Long/Integer)
radix = 16;
pos++;
} else if (str.startsWith("0", pos) && str.length() > pos + 1) {
// octal; so long as there are additional digits
radix = 8;
pos++;
} // default is to treat as decimal
if (pos > 0) {
str = str.substring(pos);
}
final BigInteger value = new BigInteger(str, radix);
return negate ? value.negate() : value;
public static BigInteger parseBigInteger(final String numberStr) {
return NumberParser.INSTANCE.parseBigInteger(numberStr);
}
/**

View File

@ -0,0 +1,251 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.math;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.util.CharUtil;
/**
* 数字检查器
*
* @author looly
* @since 6.0.0
*/
public class NumberValidator {
/**
* 是否为数字支持包括
*
* <pre>
* 110进制
* 216进制数字0x开头
* 3科学计数法形式1234E3
* 4类型标识形式123D
* 5正负数标识形式+123-234
* 6八进制数字(0开头)
* </pre>
*
* @param str 字符串值, 不可以含有任何空白字符
* @return 是否为数字
*/
public static boolean isNumber(final CharSequence str) {
if (StrUtil.isBlank(str)) {
return false;
}
final char[] chars = str.toString().toCharArray();
int sz = chars.length;
boolean hasExp = false;
boolean hasDecPoint = false;
boolean allowSigns = false;
boolean foundDigit = false;
// deal with any possible sign up front
final int start = (chars[0] == '-' || chars[0] == '+') ? 1 : 0;
if (sz > start + 1 && chars[start] == '0' && !StrUtil.contains(str, CharUtil.DOT)) { // leading 0, skip if is a decimal number
if (chars[start + 1] == 'x' || chars[start + 1] == 'X') { // leading 0x/0X
int i = start + 2;
if (i == sz) {
return false; // str == "0x"
}
// checking hex (it can't be anything else)
for (; i < chars.length; i++) {
if ((chars[i] < '0' || chars[i] > '9') && (chars[i] < 'a' || chars[i] > 'f') && (chars[i] < 'A' || chars[i] > 'F')) {
return false;
}
}
return true;
}
if (Character.isDigit(chars[start + 1])) {
// leading 0, but not hex, must be octal
int i = start + 1;
for (; i < chars.length; i++) {
if (chars[i] < '0' || chars[i] > '7') {
return false;
}
}
return true;
}
}
sz--; // don't want to loop to the last char, check it afterwords
// for type qualifiers
int i = start;
// loop to the next to last char or to the last char if we need another digit to
// make a valid number (e.g. chars[0..5] = "1234E")
while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
if (chars[i] >= '0' && chars[i] <= '9') {
foundDigit = true;
allowSigns = false;
} else if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
hasDecPoint = true;
} else if (chars[i] == 'e' || chars[i] == 'E') {
// we've already taken care of hex.
if (hasExp) {
// two E's
return false;
}
if (!foundDigit) {
return false;
}
hasExp = true;
allowSigns = true;
} else if (chars[i] == '+' || chars[i] == '-') {
if (!allowSigns) {
return false;
}
allowSigns = false;
foundDigit = false; // we need a digit after the E
} else {
return false;
}
i++;
}
if (i < chars.length) {
if (chars[i] >= '0' && chars[i] <= '9') {
// no type qualifier, OK
return true;
}
if (chars[i] == 'e' || chars[i] == 'E') {
// can't have an E at the last byte
return false;
}
if (chars[i] == '.') {
if (hasDecPoint || hasExp) {
// two decimal points or dec in exponent
return false;
}
// single trailing decimal point after non-exponent is ok
return foundDigit;
}
if (!allowSigns && (chars[i] == 'd' || chars[i] == 'D' || chars[i] == 'f' || chars[i] == 'F')) {
return foundDigit;
}
if (chars[i] == 'l' || chars[i] == 'L') {
// not allowing L with an exponent or decimal point
return foundDigit && !hasExp && !hasDecPoint;
}
// last character is illegal
return false;
}
// allowSigns is true iff the val ends in 'E'
// found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
return !allowSigns && foundDigit;
}
/**
* 判断字符串是否是整数
*
* <p>支持格式:
* <ol>
* <li>10进制, 不能包含前导零</li>
* <li>8进制(以0开头)</li>
* <li>16进制(以0x或者0X开头)</li>
* </ol>
*
* @param s 校验的字符串, 只能含有 正负号数字字符 {@literal X/x}
* @return 是否为 {@link Integer}类型
* @apiNote 6.0.0 支持8进制和16进制
* @see Integer#decode(String)
*/
public static boolean isInteger(final String s) {
if (!isNumber(s)) {
return false;
}
try {
//noinspection ResultOfMethodCallIgnored
Integer.decode(s);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是Long类型<br>
*
* <p>支持格式:
* <ol>
* <li>10进制, 不能包含前导零</li>
* <li>8进制(以0开头)</li>
* <li>16进制(以0x或者0X开头)</li>
* </ol>
*
* @param s 校验的字符串, 只能含有 正负号数字字符{@literal X/x} 后缀{@literal L/l}
* @return 是否为 {@link Long}类型
* @apiNote 6.0.0 支持8进制和16进制数字
* @since 4.0.0
*/
public static boolean isLong(final String s) {
if (!isNumber(s)) {
return false;
}
final char lastChar = s.charAt(s.length() - 1);
if (lastChar == 'l' || lastChar == 'L') {
return true;
}
try {
//noinspection ResultOfMethodCallIgnored
Long.decode(s);
} catch (final NumberFormatException e) {
return false;
}
return true;
}
/**
* 判断字符串是否是浮点数
*
* @param s String
* @return 是否为 {@link Double}类型
*/
public static boolean isDouble(final String s) {
if (StrUtil.isBlank(s)) {
return false;
}
try {
Double.parseDouble(s);
} catch (final NumberFormatException ignore) {
return false;
}
return s.contains(".");
}
/**
* 是否是质数素数<br>
* 质数表的质数又称素数指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数
*
* @param n 数字
* @return 是否是质数
*/
public static boolean isPrime(final int n) {
Assert.isTrue(n > 1, "The number must be > 1");
if (n <= 3) {
return true;
} else if ((n & 1) == 0) {
// 快速排除偶数
return false;
}
final int end = (int) Math.sqrt(n);
for (int i = 3; i <= end; i += 2) {
if (n % i == 0) {
return false;
}
}
return true;
}
}

View File

@ -74,7 +74,7 @@ import java.util.function.Supplier;
* @author looly
* @since 5.5.3
*/
public class CharSequenceUtil extends StrChecker {
public class CharSequenceUtil extends StrValidator {
/**
* 未找到的的位置表示-1表示

View File

@ -25,7 +25,7 @@ import java.util.function.Predicate;
* <li>blank定义{@code null} or 空字符串{@code ""} or 空格全角空格制表符换行符等不可见字符</li>
* </ul>
*/
public class StrChecker {
public class StrValidator {
/**
* 字符串常量{@code "null"} <br>

View File

@ -14,7 +14,7 @@ package org.dromara.hutool.core.text.placeholder;
import org.dromara.hutool.core.exceptions.HutoolException;
import org.dromara.hutool.core.lang.Assert;
import org.dromara.hutool.core.text.StrChecker;
import org.dromara.hutool.core.text.StrValidator;
import org.dromara.hutool.core.util.CharUtil;
import java.util.Objects;
@ -87,8 +87,8 @@ public class PlaceholderParser implements UnaryOperator<String> {
*/
public PlaceholderParser(
final UnaryOperator<String> processor, final String prefix, final String suffix, final char escape) {
Assert.isFalse(StrChecker.isEmpty(prefix), "开始符号不能为空");
Assert.isFalse(StrChecker.isEmpty(suffix), "结束符号不能为空");
Assert.isFalse(StrValidator.isEmpty(prefix), "开始符号不能为空");
Assert.isFalse(StrValidator.isEmpty(suffix), "结束符号不能为空");
this.processor = Objects.requireNonNull(processor);
this.open = prefix;
this.openLength = prefix.length();
@ -105,8 +105,8 @@ public class PlaceholderParser implements UnaryOperator<String> {
*/
@Override
public String apply(final String text) {
if (StrChecker.isEmpty(text)) {
return StrChecker.EMPTY;
if (StrValidator.isEmpty(text)) {
return StrValidator.EMPTY;
}
// 寻找第一个开始符号

View File

@ -1,4 +1,16 @@
package org.dromara.hutool.core.lang.func;
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.func;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.date.DateUtil;

View File

@ -1,12 +1,22 @@
package org.dromara.hutool.core.lang.func;
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.func;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;
import org.dromara.hutool.core.collection.ListUtil;
import org.dromara.hutool.core.func.LambdaFactory;
import org.dromara.hutool.core.func.SerSupplier;
import org.dromara.hutool.core.reflect.ConstructorUtil;
import org.dromara.hutool.core.reflect.lookup.LookupUtil;
import org.junit.jupiter.api.Assertions;

View File

@ -1,20 +1,30 @@
package org.dromara.hutool.core.lang.func;
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.func;
import org.dromara.hutool.core.func.*;
import org.dromara.hutool.core.lang.tuple.Tuple;
import org.dromara.hutool.core.reflect.MethodUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.FieldNameConstants;
import org.dromara.hutool.core.lang.tuple.Tuple;
import org.dromara.hutool.core.reflect.MethodUtil;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.*;
import java.util.stream.Stream;
public class LambdaUtilTest {
@ -307,4 +317,30 @@ public class LambdaUtilTest {
return func.getClass().getName();
}
}
@Test
void getInvokeMethodTest() {
Method invokeMethod = LambdaUtil.getInvokeMethod(Predicate.class);
Assertions.assertEquals("test", invokeMethod.getName());
invokeMethod = LambdaUtil.getInvokeMethod(Consumer.class);
Assertions.assertEquals("accept", invokeMethod.getName());
invokeMethod = LambdaUtil.getInvokeMethod(Runnable.class);
Assertions.assertEquals("run", invokeMethod.getName());
invokeMethod = LambdaUtil.getInvokeMethod(SerFunction.class);
Assertions.assertEquals("applying", invokeMethod.getName());
invokeMethod = LambdaUtil.getInvokeMethod(Function.class);
Assertions.assertEquals("apply", invokeMethod.getName());
}
@Test
void getInvokeMethodErrorTest() {
// 非函数接口返回异常
Assertions.assertThrows(IllegalArgumentException.class, ()->{
LambdaUtil.getInvokeMethod(LambdaUtilTest.class);
});
}
}

View File

@ -1,4 +1,16 @@
package org.dromara.hutool.core.lang.func;
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.core.func;
import org.dromara.hutool.core.collection.set.SetUtil;
import org.dromara.hutool.core.func.PredicateUtil;