mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
fix cod
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package cn.hutool.core.lang.func;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.classloader.ClassLoaderUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.text.StrPool;
|
||||
@@ -11,28 +12,42 @@ import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* 存放lambda信息
|
||||
* 存放lambda信息<br>
|
||||
* 此类是{@link SerializedLambda}信息的扩充和补充类,包括:
|
||||
* <ul>
|
||||
* <li>实例化后的对象方法参数类型,一般用于方法引用</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author VampireAchao
|
||||
*/
|
||||
public class LambdaInfo {
|
||||
|
||||
private static final Type[] EMPTY_TYPE = new Type[0];
|
||||
// 实例对象的方法参数类型
|
||||
private final Type[] instantiatedMethodParameterTypes;
|
||||
// 方法或构造的参数类型
|
||||
private final Type[] parameterTypes;
|
||||
private final Type returnType;
|
||||
// 方法名或构造名称
|
||||
private final String name;
|
||||
private final Executable executable;
|
||||
private final Class<?> clazz;
|
||||
private final SerializedLambda lambda;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param executable 构造对象{@link Constructor}或方法对象{@link Method}
|
||||
* @param lambda 实现了序列化接口的lambda表达式
|
||||
*/
|
||||
public LambdaInfo(final Executable executable, final SerializedLambda lambda) {
|
||||
Assert.notNull(executable, "executable must be not null!");
|
||||
// return type
|
||||
final boolean isMethod = executable instanceof Method;
|
||||
final boolean isConstructor = executable instanceof Constructor;
|
||||
Assert.isTrue(isMethod || isConstructor, "Unsupported executable type: " + executable.getClass());
|
||||
this.returnType = isMethod ?
|
||||
((Method)executable).getGenericReturnType() : ((Constructor<?>)executable).getDeclaringClass();
|
||||
((Method) executable).getGenericReturnType() : ((Constructor<?>) executable).getDeclaringClass();
|
||||
|
||||
// lambda info
|
||||
this.parameterTypes = executable.getGenericParameterTypes();
|
||||
@@ -42,15 +57,89 @@ public class LambdaInfo {
|
||||
this.lambda = lambda;
|
||||
|
||||
// types
|
||||
final int index = lambda.getInstantiatedMethodType().indexOf(";)");
|
||||
this.instantiatedMethodParameterTypes = (index > -1) ? getInstantiatedMethodParamTypes(lambda, index) : EMPTY_TYPE;
|
||||
final String instantiatedMethodType = lambda.getInstantiatedMethodType();
|
||||
final int index = instantiatedMethodType.indexOf(";)");
|
||||
this.instantiatedMethodParameterTypes = (index > -1) ?
|
||||
getInstantiatedMethodParamTypes(instantiatedMethodType.substring(1, index + 1)) : EMPTY_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 实例方法参数类型
|
||||
*
|
||||
* @return 实例方法参数类型
|
||||
*/
|
||||
public Type[] getInstantiatedMethodParameterTypes() {
|
||||
return instantiatedMethodParameterTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得构造或方法参数类型列表
|
||||
*
|
||||
* @return 参数类型列表
|
||||
*/
|
||||
public Type[] getParameterTypes() {
|
||||
return parameterTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取返回值类型(方法引用)
|
||||
*
|
||||
* @return 返回值类型
|
||||
*/
|
||||
public Type getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法或构造名称
|
||||
*
|
||||
* @return 方法或构造名称
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字段名称,主要用于方法名称截取,方法名称必须为getXXX、isXXX、setXXX
|
||||
*
|
||||
* @return getter或setter对应的字段名称
|
||||
*/
|
||||
public String getFieldName() {
|
||||
return BeanUtil.getFieldName(getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法或构造对象
|
||||
*
|
||||
* @return 方法或构造对象
|
||||
*/
|
||||
public Executable getExecutable() {
|
||||
return executable;
|
||||
}
|
||||
|
||||
/**
|
||||
* 方法或构造所在类
|
||||
*
|
||||
* @return 方法或构造所在类
|
||||
*/
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获得Lambda表达式对象
|
||||
*
|
||||
* @return 获得Lambda表达式对象
|
||||
*/
|
||||
public SerializedLambda getLambda() {
|
||||
return lambda;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda对象的方法签名信息,解析获得实际的参数类型
|
||||
*/
|
||||
private Type[] getInstantiatedMethodParamTypes(SerializedLambda lambda, int index) {
|
||||
final String className = lambda.getInstantiatedMethodType().substring(1, index + 1);
|
||||
private static Type[] getInstantiatedMethodParamTypes(final String className) {
|
||||
final String[] instantiatedTypeNames = className.split(";");
|
||||
final Type[] types = new Type[instantiatedTypeNames.length];
|
||||
for (int i = 0; i < instantiatedTypeNames.length; i++) {
|
||||
@@ -72,32 +161,4 @@ public class LambdaInfo {
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
public Type[] getInstantiatedMethodParameterTypes() {
|
||||
return instantiatedMethodParameterTypes;
|
||||
}
|
||||
|
||||
public Type[] getParameterTypes() {
|
||||
return parameterTypes;
|
||||
}
|
||||
|
||||
public Type getReturnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Executable getExecutable() {
|
||||
return executable;
|
||||
}
|
||||
|
||||
public Class<?> getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
public SerializedLambda getLambda() {
|
||||
return lambda;
|
||||
}
|
||||
}
|
||||
|
@@ -28,27 +28,29 @@ public class LambdaUtil {
|
||||
* 通过对象的方法或类的静态方法引用,获取lambda实现类
|
||||
* 传入lambda无参数但含有返回值的情况能够匹配到此方法:
|
||||
* <ul>
|
||||
* <li>引用特定对象的实例方法:<pre>{@code
|
||||
* MyTeacher myTeacher = new MyTeacher();
|
||||
* Class<MyTeacher> supplierClass = LambdaUtil.getRealClass(myTeacher::getAge);
|
||||
* Assert.assertEquals(MyTeacher.class, supplierClass);
|
||||
* }</pre></li>
|
||||
* <li>引用静态无参方法:<pre>{@code
|
||||
* Class<MyTeacher> staticSupplierClass = LambdaUtil.getRealClass(MyTeacher::takeAge);
|
||||
* Assert.assertEquals(MyTeacher.class, staticSupplierClass);
|
||||
* }</pre></li>
|
||||
* <li>引用特定对象的实例方法:<pre>{@code
|
||||
* MyTeacher myTeacher = new MyTeacher();
|
||||
* Class<MyTeacher> supplierClass = LambdaUtil.getRealClass(myTeacher::getAge);
|
||||
* Assert.assertEquals(MyTeacher.class, supplierClass);
|
||||
* }</pre>
|
||||
* </li>
|
||||
* <li>引用静态无参方法:<pre>{@code
|
||||
* Class<MyTeacher> staticSupplierClass = LambdaUtil.getRealClass(MyTeacher::takeAge);
|
||||
* Assert.assertEquals(MyTeacher.class, staticSupplierClass);
|
||||
* }</pre>
|
||||
* </li>
|
||||
* </ul>
|
||||
* 在以下场景无法获取到正确类型
|
||||
* <pre>{@code
|
||||
* // 枚举测试,只能获取到枚举类型
|
||||
* Class<Enum<?>> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
|
||||
* Assert.assertEquals(Enum.class, enumSupplierClass);
|
||||
* // 调用父类方法,只能获取到父类类型
|
||||
* Class<Entity<?>> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
|
||||
* Assert.assertEquals(Entity.class, superSupplierClass);
|
||||
* // 引用父类静态带参方法,只能获取到父类类型
|
||||
* Class<Entity<?>> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
|
||||
* Assert.assertEquals(Entity.class, staticSuperFunctionClass);
|
||||
* // 枚举测试,只能获取到枚举类型
|
||||
* Class<Enum<?>> enumSupplierClass = LambdaUtil.getRealClass(LambdaUtil.LambdaKindEnum.REF_NONE::ordinal);
|
||||
* Assert.assertEquals(Enum.class, enumSupplierClass);
|
||||
* // 调用父类方法,只能获取到父类类型
|
||||
* Class<Entity<?>> superSupplierClass = LambdaUtil.getRealClass(myTeacher::getId);
|
||||
* Assert.assertEquals(Entity.class, superSupplierClass);
|
||||
* // 引用父类静态带参方法,只能获取到父类类型
|
||||
* Class<Entity<?>> staticSuperFunctionClass = LambdaUtil.getRealClass(MyTeacher::takeId);
|
||||
* Assert.assertEquals(Entity.class, staticSuperFunctionClass);
|
||||
* }</pre>
|
||||
*
|
||||
* @param func lambda
|
||||
@@ -60,7 +62,10 @@ public class LambdaUtil {
|
||||
@SuppressWarnings("unchecked")
|
||||
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);
|
||||
return (Class<R>) Opt.of(lambdaInfo)
|
||||
.map(LambdaInfo::getInstantiatedMethodParameterTypes)
|
||||
.filter(types -> types.length != 0).map(types -> types[types.length - 1])
|
||||
.orElseGet(lambdaInfo::getClazz);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -10,6 +10,8 @@ import java.util.stream.Stream;
|
||||
/**
|
||||
* SerBiConsumer
|
||||
*
|
||||
* @param <T> 第一个参数类型
|
||||
* @param <U> 第二个参数类型
|
||||
* @author VampireAchao
|
||||
*/
|
||||
@FunctionalInterface
|
||||
@@ -24,7 +26,8 @@ public interface SerBiConsumer<T, U> extends BiConsumer<T, U>, Serializable {
|
||||
*/
|
||||
@SafeVarargs
|
||||
static <T, U> SerBiConsumer<T, U> multi(final SerBiConsumer<T, U>... consumers) {
|
||||
return Stream.of(consumers).reduce(SerBiConsumer::andThen).orElseGet(() -> (o, q) -> {});
|
||||
return Stream.of(consumers).reduce(SerBiConsumer::andThen).orElseGet(() -> (o, q) -> {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,6 +82,7 @@ public interface SerBiConsumer<T, U> extends BiConsumer<T, U>, Serializable {
|
||||
* @return 什么也不做
|
||||
*/
|
||||
static <T, U> SerBiConsumer<T, U> nothing() {
|
||||
return (l, r) -> {};
|
||||
return (l, r) -> {
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -30,10 +30,10 @@ public interface SerFunction<T, R> extends Function<T, R>, Serializable {
|
||||
* @return the function result
|
||||
*/
|
||||
@Override
|
||||
default R apply(T t) {
|
||||
default R apply(final T t) {
|
||||
try {
|
||||
return applying(t);
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
throw new UtilException(e);
|
||||
}
|
||||
}
|
||||
|
@@ -11,9 +11,10 @@ import java.util.stream.Stream;
|
||||
*
|
||||
* @author VampireAchao
|
||||
* @see Supplier
|
||||
* @param <R> 返回值类型
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SerSupplier<T> extends Supplier<T>, Serializable {
|
||||
public interface SerSupplier<R> extends Supplier<R>, Serializable {
|
||||
|
||||
/**
|
||||
* Gets a result.
|
||||
@@ -21,7 +22,7 @@ public interface SerSupplier<T> extends Supplier<T>, Serializable {
|
||||
* @return a result
|
||||
* @throws Exception wrapped checked exceptions
|
||||
*/
|
||||
T getting() throws Exception;
|
||||
R getting() throws Exception;
|
||||
|
||||
/**
|
||||
* Gets a result.
|
||||
@@ -29,7 +30,7 @@ public interface SerSupplier<T> extends Supplier<T>, Serializable {
|
||||
* @return a result
|
||||
*/
|
||||
@Override
|
||||
default T get() {
|
||||
default R get() {
|
||||
try {
|
||||
return getting();
|
||||
} catch (final Exception e) {
|
||||
|
@@ -7,7 +7,9 @@ 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.LambdaInfo;
|
||||
import cn.hutool.core.lang.func.LambdaUtil;
|
||||
import cn.hutool.core.lang.func.SerFunction;
|
||||
import cn.hutool.core.lang.func.SerSupplier;
|
||||
import cn.hutool.core.lang.getter.TypeGetter;
|
||||
|
||||
@@ -352,6 +354,19 @@ public class Dict extends CustomKeyMap<String, Object> implements TypeGetter<Str
|
||||
return getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据lambda的方法引用,获取
|
||||
*
|
||||
* @param func 方法引用
|
||||
* @param <P> 参数类型
|
||||
* @param <T> 返回值类型
|
||||
* @return 获取表达式对应属性和返回的对象
|
||||
*/
|
||||
public <P, T> T get(final SerFunction<P, T> func) {
|
||||
final LambdaInfo lambdaInfo = LambdaUtil.resolve(func);
|
||||
return get(lambdaInfo.getFieldName(), lambdaInfo.getReturnType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得特定类型值
|
||||
*
|
||||
|
@@ -3,14 +3,15 @@ package cn.hutool.core.lang;
|
||||
import cn.hutool.core.builder.GenericBuilder;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.map.Dict;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.hutool.core.lang.OptTest.User;
|
||||
|
||||
public class DictTest {
|
||||
@Test
|
||||
public void dictTest(){
|
||||
@@ -70,5 +71,16 @@ public class DictTest {
|
||||
dict.setFields(user::getNickname, user::getUsername);
|
||||
Assert.assertEquals("hutool", dict.get("username"));
|
||||
Assert.assertNull(dict.get("nickname"));
|
||||
|
||||
// get by lambda
|
||||
Assert.assertEquals("hutool", dict.get(User::getUsername));
|
||||
}
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
static class User {
|
||||
private String username;
|
||||
private String nickname;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user