Java 如何通过反射从静态方法获取谓词?
给定一个由静态谓词方法组成的类,我希望通过反射访问它们,并将它们转换为Java 如何通过反射从静态方法获取谓词?,java,reflection,predicate,Java,Reflection,Predicate,给定一个由静态谓词方法组成的类,我希望通过反射访问它们,并将它们转换为谓词类型 public class MyPredicates { public static boolean isNull(Object obj) { return obj == null; } public static boolean hasNegativeHashcode(Object obj) { return obj.hashCode() < 0;
谓词
类型
public class MyPredicates {
public static boolean isNull(Object obj) {
return obj == null;
}
public static boolean hasNegativeHashcode(Object obj) {
return obj.hashCode() < 0;
}
}
公共类MyPredicates{
公共静态布尔值isNull(对象obj){
返回obj==null;
}
公共静态布尔hasNegativeHashcode(对象obj){
返回obj.hashCode()<0;
}
}
通常,我会编写以下代码来获取谓词:
Predicate<Object> isNull = MyPredicates::isNull;
谓词isNull=MyPredicates::isNull;
然而,我不知道如何使用反射来实现这一点。我的意图是为这些方法创建一个注释,并通过反射获得它们,从而为我的框架创建一个可用谓词列表
我想到了三种可能的方法,对我来说没有一种是好的
Method
那样保留它,调用invoke()
并将返回的对象转换为布尔值。然而,这将很难阅读,这意味着我无法在运行时检查类型
谓词
,但这将涉及额外的开销谓词吗
谓词
)的情况下,访问这些方法而不增加太多开销的合适方式是什么TL;DR:直接从静态方法返回
谓词
,并将其存储以备将来使用(可能存储在方法名称为键的映射中),以消除反射访问的速度瓶颈
public static Predicate<Object> isNull() {
return obj -> obj == null;
}
翻译为
list.filter(indy(MH(metaFactory), MH(invokeVirtual Predicate.apply), MH(invokeVirtual String.isEmpty))()))
这意味着谓词在运行时不存在,除非您在代码中编写它。可能有一种通过反射API获取它的方便方法,但据我所知,没有。你也许能用英语写一些类似的东西;然而,我认为这会给代码增加不必要的复杂性
以下是实现预期行为的4种不同方法的基准,包括问题中提到的方法:
Benchmark Mode Cnt Score Error Units
MyBenchmark.testNormal thrpt 30 362.782 ± 13.521 ops/us
MyBenchmark.testReflectionInvoke thrpt 30 60.440 ± 1.394 ops/us
MyBenchmark.testReflectionWrappedPredicate thrpt 30 62.948 ± 0.846 ops/us
MyBenchmark.testReflectionReturnedPredicate thrpt 30 381.780 ± 5.265 ops/us
testNormal通过:
运算符访问谓词
testReflectionInvoke直接使用invoke()
方法
testReflectionWrappedPredicate将invoke()
方法包装为Precicate
testReflectionReturnedPredicate使用返回谓词的方法,因此反射只被调用一次
在本例中,谓词是缓存的,因为我们不测试获取谓词的速度,而是假设它只执行一次
从结果中可以看出,反射比正常访问谓词慢6倍。因此,在我看来,最干净/最可维护的方法是让不带参数的方法返回谓词
类型,而不是布尔
public static Predicate<Object> isNull() {
return obj -> obj == null;
}
公共静态谓词isNull(){
返回obj->obj==null;
}
基准测试使用了3个fork、4个预热迭代和10个迭代
以下是我用于测试的代码,如果您想自己运行基准测试(使用JMH框架进行基准测试):
公共类MyBenchmark{
公共静态谓词normal=MyBenchmark::isNull;
公共静态方法反射波;
公共静态谓词reflectionWrappedPredicate;
公共静态谓词reflectionReturnedPredicate;
静止的{
试一试{
方法m1=MyBenchmark.class.getMethod(“isNull”,Object.class);
反射率为m1;
reflectionWrappedPredicate=a->{
试一试{
返回值(布尔值)m1.invoke(null,a);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex){
返回false;
}
};
方法m2=MyBenchmark.class.getMethod(“isNull”);
reflectionReturnedPredicate=(谓词)m2.invoke(null);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex){
例如printStackTrace();
};
}
@基准
@输出时间单位(时间单位,微秒)
公共布尔testNormal(){
谓词p=正常;
返回p.test(this)| p.test(null);
}
@基准
@输出时间单位(时间单位,微秒)
公共布尔testReflectionInvoke(){
试一试{
方法m=反射波;
return(boolean)m.invoke(null,this)|(boolean)m.invoke(null,(Object)null);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException ex){
例如printStackTrace();
返回false;
}
}
@基准
@输出时间单位(时间单位,微秒)
公共布尔testReflectionWrappedPredicate(){
谓词p=reflectionWrappedPredicate;
返回p.test(this)| p.test(null);
}
@基准
@输出时间单位(时间单位,微秒)
公共布尔testReflectionReturnedPredicate(){
谓词p=reflectionReturnedPredicate;
返回p.test(this)| p.test(null);
}
公共静态布尔值isNull(对象obj){
返回obj==null;
}
公共静态谓词isNull(){
返回obj->obj==null;
}
}
我不明白你为什么需要反思。难道您的注释处理器不知道什么
public static Predicate<Object> isNull() {
return obj -> obj == null;
}
public class MyBenchmark {
public static Predicate<Object> normal = MyBenchmark::isNull;
public static Method reflectionInvoke;
public static Predicate<Object> reflectionWrappedPredicate;
public static Predicate<Object> reflectionReturnedPredicate;
static {
try {
Method m1 = MyBenchmark.class.getMethod("isNull", Object.class);
reflectionInvoke = m1;
reflectionWrappedPredicate = a -> {
try {
return (boolean)m1.invoke(null, a);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
return false;
}
};
Method m2 = MyBenchmark.class.getMethod("isNull");
reflectionReturnedPredicate = (Predicate)m2.invoke(null);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException ex) {
ex.printStackTrace();
};
}
@Benchmark
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testNormal() {
Predicate<Object> p = normal;
return p.test(this) | p.test(null);
}
@Benchmark
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testReflectionInvoke() {
try {
Method m = reflectionInvoke;
return (boolean)m.invoke(null, this) | (boolean)m.invoke(null, (Object)null);
}
catch(IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException ex) {
ex.printStackTrace();
return false;
}
}
@Benchmark
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testReflectionWrappedPredicate() {
Predicate<Object> p = reflectionWrappedPredicate;
return p.test(this) | p.test(null);
}
@Benchmark
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public boolean testReflectionReturnedPredicate() {
Predicate<Object> p = reflectionReturnedPredicate;
return p.test(this) | p.test(null);
}
public static boolean isNull(Object obj) {
return obj == null;
}
public static Predicate<Object> isNull() {
return obj -> obj == null;
}
}