Home > Net >  Why do the following code prints the stack trace and why is a.toString() in the return statement not
Why do the following code prints the stack trace and why is a.toString() in the return statement not

Time:06-01

Following is the complete code -

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;

class A2<T> {
    T ob;
    A2(T ob) {
        this.ob = ob;
    }
    @Annos(str="T example")
    T retob() {
        return ob;
    }
    @Override
    public String toString() {
        Annotation a = null;
        try {
            Class<?> c = this.getClass();
            Method m = c.getMethod("retob");
            a = m.getAnnotation(Annos.class);
        }catch(NoSuchMethodException NSMe) {
            NSMe.printStackTrace();
        }
        return a==null?"EMPTY":a.toString();
    }
    public static void main(String args[]) {
        System.out.println(new A2<Integer>(2).toString());
    }
}

@Retention(RetentionPolicy.RUNTIME)
@interface Annos {
    String str();
}

If I have override the toString() method then how can a.toString() in the return statement as well as in the main method work?

Here is the output -

java.lang.NoSuchMethodException: A2.retob()
        at java.base/java.lang.Class.getMethod(Class.java:2227)
        at A2.toString(A2.java:20)
        at A2.main(A2.java:28)
EMPTY

Why is it not able to get the method retob?

CodePudding user response:

The solution is to change

Method m = c.getMethod("retob");

to

Method m = c.getDeclaredMethod("retob");

This is needed because your retob method is not public.

From the documentation of getMethod:

[The class's] declared public instance and static methods as returned by getDeclaredMethods() and filtered to include only public methods that match given name and parameterTypes

This means that getMethod uses getDeclaredMethod but then ignores the method if it's not public. Using getDeclaredMethod directly solves that problem.

About your question regarding the toString:

return a==null?"EMPTY":a.toString(); still works because a is null. That's why "EMPTY" is returned.

  • Related