我有一个用例,使用反射来获取Function
对象 1 的参数和返回值类型会很有用。
但是我发现遵循由lambda表达式导致的函数对象的令人惊讶的行为:该对象没有具有特定类型的import java.lang.reflect.Type;
import java.lang.reflect.Method;
import java.util.function.Function;
public class Trying {
public static void main(String[] args) {
Function<Integer, Double> lambda = i -> i.doubleValue();
Function<Integer, Double> methodRef = Integer::doubleValue;
Function<Integer, Double> anon = new Function<Integer, Double>() {
@Override
public Double apply(Integer i) {
return i.doubleValue();
}
};
printType("lambda", lambda);
printType("methodRef", methodRef);
printType("anon", anon);
}
private static void printType(String name, Function<?, ?> f) {
System.out.println("### " + name);
System.out.println("super: " + f.getClass().getSuperclass().getSimpleName());
for (Type i : f.getClass().getGenericInterfaces()) {
System.out.println("interface: " + i);
}
for (Method m : f.getClass().getDeclaredMethods()) {
System.out.println("name: " + m.getName() + ", bridge: " + m.isBridge()
+ ", arg type: " + m.getParameterTypes()[0].getSimpleName()
+ ", return type: " + m.getReturnType().getSimpleName());
}
System.out.println();
}
}
方法。
示例代码:
### methodRef
super: Object
interface: interface java.util.function.Function
name: apply, bridge: false, arg type: Object, return type: Object
### lambda
super: Object
interface: interface java.util.function.Function
name: apply, bridge: false, arg type: Object, return type: Object
### anon
super: Object
interface: java.util.function.Function<java.lang.Integer, java.lang.Double>
name: apply, bridge: false, arg type: Integer, return type: Double
name: apply, bridge: true, arg type: Object, return type: Object
此代码打印以下内容:
testreturn.py
1:我想使用此信息为数据绑定API创建默认转换器。
答案 0 :(得分:0)
首先,我要感谢您发布一个非常完整的代码片段,只需要进行一些修改即可编译和运行。它让我们更容易。
我的简短回答是不要做。编写依赖于这种反射工作的代码会有问题...可能会有一些技巧让它像上面所示使用内部类一样工作,但它最终会咬你,所以我的建议是远离这种做法。
相反,您可以创建一个“类型化”函数子类,使用这样的有效Java惯用语来解决问题:
df.isnull().values.sum()
然后使用代码实例化这些函数的方式如下:
abstract class TypedFunction<T, U> implements Function<T, U> {
final Class<T> inClass;
final Class<U> outClass;
TypedFunction(final Class<T> inClass, final Class<U> outClass) {
this.inClass = inClass;
this.outClass = outClass;
}
static <TT, UU> TypedFunction<TT, UU> make(
final Class<TT> inClass,
final Class<UU> outClass,
final Function<? super TT, ? extends UU> func) {
return new TypedFunction<TT, UU>(inClass, outClass) {
@Override
UU apply(final TT in) {
return func.apply(in);
}
};
}
}
反过来,用于解析in和out类的反射代码只是访问传递的TypedFunction<Integer, Double> lambda = TypedFunction.make(Integer.class, Double.class, i -> i.doubleValue());
TypedFunction<Integer, Double> methodRef = TypedFunction.make(Integer.class, Double.class, Integer::doubleValue);
TypedFunction<Integer, Double> anon = TypedFunction.make(Integer.class, Double.class, new Function<Integer, Double>() {
@Override
public Double apply(Integer i) {
return i.doubleValue();
}
};
TypedFunction<Integer, Double> anonSimple =
new TypedFunction<Integer, Double>(Integer.class, Double.class) {
@Override
public Double apply(Integer i) {
return i.doubleValue();
}
};
上的inClass
和outClass
字段。当然,如果这些类型恰好是通用类型,它会返回“原始”类型而不是通用形式,但我认为我们应该离开它。
如果包含TypedFunction<?, ?>
和Integer.class
似乎很乏味,你可以创建一个二阶函数,其构造函数接受Double.class
和T
类引用,它本身就是一个函数来自基础U
到其Function<T, U>
包装版本。