Home > Software engineering >  Java: How do I invoke methods that are annotated and declared within an interface
Java: How do I invoke methods that are annotated and declared within an interface

Time:06-30

File A.java:

public interface A {
    @Property(propertyName = "empoloyee.name")
    String getEmployeeName();

    @Property(propertyName = "employee.age")
    String getEmployeeAge();
}

File B.java:

public class B {
    public static void main(String[] args) {
        for (Method method: A.class.getMethods()) {
            Property property = method.getAnnotation(Property.class);

            System.out.println("Property Name: "   property.propertyName());
            System.out.println("Property Value: "   method.invoke());
        }
    }
}

Property.class:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Property {
    String propertyName() default "";

    String defaultValue() default "";
}

As shown in the above code snippet, my requirement is to invoke all the methods declared in A.class, in a loop.

Since these methods are annotated, just invoking them will return the property value. method.invoke() is giving me error. How do I resolve this issue?

CodePudding user response:

method.invoke needs object to pass for invoking the method so you will have pass an object of any class implementing interface A, like below -

public class C implements A{
@Override
public String getEmployeeName() {
    return "xyz";
}

@Override
public String getEmployeeAge() {
    return "22";
}
}

Then your main method will be like this -

public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
    C c = new C();
    for (Method method: A.class.getMethods()) {
        Property property = method.getAnnotation(Property.class);

        System.out.println("Property Name: "   property.propertyName());
        System.out.println("Property Value: "   method.invoke(c));
    }
}

CodePudding user response:

I did some modifications to your code and I am hoping it helps. first of all, A is not a class it is just an interface and has methods with nobody, so in my case, I made an Employee class that implements the A interface:

public class Employee implements A {
    private String employeeName;
    private String employeeAge;

    public Employee(String name, String age) {
        this.employeeName = name;
        this.employeeAge = age;

    }
    
     
    public String getEmployeeName() {
        // TODO Auto-generated method stub
        return employeeName;
    }

    public String getEmployeeAge() {
        // TODO Auto-generated method stub
        return employeeAge;
    }
    
    

}

then inside Class B I called the Employee class

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class B {

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        
        for (Method method: A.class.getMethods()) {
            Employee em = new Employee("Roy", "20");

            System.out.println("Property Name: "   em.getEmployeeName());
            System.out.println("Property Value: "   method.invoke(em));
        }
           
        }
    }

Property Annotation:

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

// this annotation target only methods 
@Target(ElementType.METHOD)
public @interface Property {

    String propertyName() default "hi";

}

A interface:

// A is interface not a class 
public interface A {

    @Property(propertyName = "employee.name")
    // this method is abstract: has no body
    String getEmployeeName();

    @Property(propertyName ="employee.age" )
    // for good practice this should be integer instead of string
    String getEmployeeAge();

}

I hope this answer your question. thanks

  • Related