I'm looking for some help in optimizing my code and write it using less number of lines. I have a Class say A which has few methods defined like below:
Class A{
public void doSomethingA(){
}
public void doSomethingB(){
}
public void doSomethingC(){
}
public void verifySomethingXYZ(){
}
public void verifySomethingLMN(){
}
}
Now I have a separate class say B and methods written like below
Class B{
public void test(){
}
public void verifyMyMethods(){
A objA = new A();
objA.doSomethingA();
test();
objA.doSomethingB();
test();
objA.doSomethingC();
test();
}
}
All of this code runs well. I'm just trying to see if there is a better way I can keep calling those methods like objA.doSomethingA() inside verifyMyMethods() so I can do the same work using less number of code lines.
I would like to call methods doSomethingA(), doSomethingB(), doSomethingC() etc. in a loop. But not sure how it can be done. One approach was to use Java.lang.Class.getMethod(). But this will return all the methods defined in a class.
I did check this [https://stackoverflow.com/questions/12566107/how-to-call-multiple-methods-using-loop-in-java ] exisitng post, but my problem is I just do not want to call all the methods defined inside class A. Only some of them. And since I will be calling some 10-20 methods from Class A in Class B, I would like to do this in slightly better fashion.
There is another solution I saw in Python [https://stackoverflow.com/questions/55458933/how-to-call-multiple-methods-of-a-class-in-a-loop]
name = YourClass()
methods = [name.alex, name.john, name.claire ] # ...
for m in methods:
m()
But how can this be done in Java? Here is what I tried. But it gives null pointer exception.
public void try(){
List<String> l = Lists.newArrayList("objA.doSomethingA","objA.doSomethingB","objA.doSomethingC");
for (String i : l){
try{
Method mett =objA.getClass().getMethod(i); // null pointer exception thrown for this line
mett.invoke(i);
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e){
}
}
CodePudding user response:
You must wrap the method invocations in a function to achieve that. Consumer is a good candidate for your case.
Represents an operation that accepts a single input argument and returns no result
An implementation may look like this:
class MethodInvocation implements Consumer<A> {
@Override
public void accept(A a) {
a.doSomethingA();
}
}
That's too long to do for every method invocation and since Consumer
is a functional interface, we can just use lambdas or method references.
public class Temp {
public static void main(String[] args) throws Exception {
A objA = new A();
List<Consumer<A>> consumers = Arrays.asList(a -> a.doSomethingA(), A::doSomethingB, A::doSomethingC);
for (Consumer<A> consumer : consumers) {
consumer.accept(objA);
}
}
}
CodePudding user response:
Just another solution:
public class A {
public void doSomethingA(){
System.out.println("Calling doSomethingA");
}
public void doSomethingB(){
System.out.println("Calling doSomethingB");
}
public void doSomethingC(){
System.out.println("Calling doSomethingC");
}
public void verifySomethingXYZ(){
System.out.println("Calling verifySomethingXYZ");
}
public void verifySomethingLMN(){
System.out.println("Calling verifySomethingLMN");
}
}
public class Main {
public static void main(String[] args) {
List<String> methodsToCall = new ArrayList<>(Arrays.asList("doSomethingA", "doSomethingB", "doSomethingC"));
callDesiredMethods(methodsToCall);
}
public static void callDesiredMethods(List<String> methodsToCall) {
Class clazz = A.class;
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if (methodsToCall.contains(method.getName())) {
try {
method.invoke(clazz.newInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
}
}
}
}