所以,我有以下课程:
public class MainClass{
public void run(String infoOne, String infoTwo, String infoThree, String infoFour, String infoFive, String infoSix){
SomeClass someClass = new SomeClass();
someClass.runSomeMethod();
someClass.runSomeMethodTwo( infoOne);
someClass.runSomeMethodThree( infoThree, infoOne, infoSix);
someClass.runSomeMethodFour( infoTwo, infoFive);
someClass.runSomeMethodFive(infoThree, infoFive, infoOne, infoSix);
}
}
public class SomeClass{
public boolean runSomeMethod(){
// do something
}
public boolean runSomeMethodTwo(String arg){
// do something
}
public boolean runSomeMethodThree(String argOne, String argTwo, String argThree){
// do something
}
public boolean runSomeMethodFour(String argOne, String argTwo){
// do something
}
public boolean runSomeMethodFive(String argOne, String argTwo, String argThree, String argFour){
// do something
}
}
正如你所看到的那样,一系列方法只将Strings作为参数(但每次都有不同的数量)。我现在想要的是将每个方法包装在try catch块中并记录一些结果。为此,我想在其间设置一个处理日志记录的方法:
log(SomeClass::runSomeMethodFour);
public void log(????? method, String...args){
try{
if(method.execute(args);
System.out.println("Success!");
} else {
System.out.println("Failed to execute!");
}
} catch (Exception e){
e.printStackTrace();
}
}
这有可能吗?要将动态数量的参数传递给lambda函数?或者我可以用泛型做点什么吗?
答案 0 :(得分:2)
JLS描述了方法参考表达式:
方法引用的编译时声明是表达式引用的方法。在特殊情况下,编译时声明实际上并不存在,但它是一个表示类实例创建或数组创建的名义方法。编译时声明的选择取决于表达式所针对的函数类型,就像方法调用的编译时声明依赖于调用的参数一样。
如果T是函数接口类型(第9.8节)且表达式与地面目标类型的函数类型一致,则方法引用表达式在赋值上下文,调用上下文或具有目标类型T的转换上下文中是兼容的源自T。
方法引用表达式必须在编译时准确分配Function Interface。和功能接口是 SAM 接口。所以你不能在运行时通过方法引用表达式动态绑定方法处理程序。
但您可以使用reflection或invoke api来实现它。
让我们看看每个方法表达式引用SomeClass
中的函数接口结果是指不同的函数接口类型:
SomeClass it = new SomeClass();
BooleanSupplier first1 = it::runSomeMethod;//bound
Predicate<SomeClass> first2 = SomeClass::runSomeMethod;//unbound
Predicate<String> second1 = it::runSomeMethodTwo;//bound
BiPredicate<SomeClass, String> second2 = SomeClass::runSomeMethodTwo;//unbound
...
答案 1 :(得分:2)
无需创建复杂的基于反射的解决方案。您的问题源于不必要的尝试分离方法和参数参数,而不是仅仅封装整个操作,如
public class MainClass {
public void run(String infoOne, String infoTwo, String infoThree,
String infoFour, String infoFive, String infoSix) {
SomeClass someClass = new SomeClass();
log(() -> someClass.runSomeMethod());
log(() -> someClass.runSomeMethodTwo(infoOne));
log(() -> someClass.runSomeMethodThree(infoThree, infoOne, infoSix));
log(() -> someClass.runSomeMethodFour(infoTwo, infoFive));
log(() -> someClass.runSomeMethodFive(infoThree, infoFive, infoOne, infoSix));
}
public void log(BooleanSupplier method) {
try {
if(method.getAsBoolean()) {
System.out.println("Success!");
} else {
System.out.println("Failed to execute!");
}
} catch (Exception e ){
e.printStackTrace();
}
}
}
对于log
方法的工作,只有boolean
返回值是相关的,它与BooleanSupplier
的功能签名相匹配。
答案 2 :(得分:1)
听说&#34;反思&#34;作为Oliver Charlesworth的评论,我提出了以下解决方案:
public class Test {
static Test testLogger = new Test(); //This should be another class ofcourse, but it doesn't matter for this example
public static void main(String[] args) throws NoSuchMethodException, SecurityException{
Test test = new Test();
run(test, "something", "hi", "hai", "blaa");
}
public static void run(Object pageObjectModel, String methodName, String...arguments){
Class<String>[] args = new Class[arguments.length];
Arrays.fill(args, String.class);
try {
testLogger.log(pageObjectModel, pageObjectModel.getClass().getMethod(methodName, args), arguments);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
}
private void log(Object pageObjectModel, Method method, String...arguments) {
try {
if((Boolean)method.invoke(pageObjectModel, (Object[])arguments)){
System.out.println("Success!");
} else {
System.out.println("Fail!");
}
} catch (Exception e){
e.printStackTrace();
}
}
public boolean something(String one, String two, String three){
System.out.println(one+", "+two+", "+three);
return true;
}
}
这对我想要实现的目标来说似乎是完美的。虽然我不喜欢反思,因为它有不好的经验(给出混淆代码的问题),我觉得这个项目很好。
感谢您帮助我朝着正确的方向前进!