Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getDeclaredMethods() in Class class

public Method[] getDeclaredMethods() throws SecurityException

has documentation as below.

/**
     *
     * Returns an array containing {@code Method} objects reflecting all the
     * declared methods of the class or interface represented by this {@code
     * Class} object, including public, protected, default (package)
     * access, and private methods, but excluding inherited methods.

<p> If this {@code Class} object represents a type that has multiple
             * declared methods with the same name and parameter types, but different
             * return types, then the returned array has a {@code Method} object for
             * each such method.
         *

how can a single class have two [declared] methods with different return types, same name and same parameter types?

like image 418
Pushparaj Avatar asked Jan 29 '23 22:01

Pushparaj


2 Answers

It's not possible in the Java language to declare two methods with same names and parameter types but different return types.

The Java Virtual Machine (JVM) however has no problem handling methods like that.

There is a way to create such methods implicitly, by overriding a base class method with a more specific return type.

If a base class has a method Object foo() and your class overrides it with a method String foo() then the .class file of your class will have a synthetic (and thus not "visible") method Object foo() and a "normal" method String foo(). The Object foo() method exists for compatibility with classes that want to treat your class as an instance of the base class and don't know about the String foo() override.

Additionally some non-Java languages might let you create classes with those kinds of method explicitly.

like image 196
Joachim Sauer Avatar answered Jan 31 '23 11:01

Joachim Sauer


A simple example:

import java.lang.reflect.Method;
import java.util.concurrent.Callable;

public class MultipleMethods implements Callable<String> {
    public static void main(String[] args) {
        for(Method m: MultipleMethods.class.getDeclaredMethods()) {
            System.out.println(m);
        }
    }

    @Override
    public String call() {
        return "just an example";
    }
}

Test on ideone.com

public static void MultipleMethods.main(java.lang.String[])
public java.lang.Object MultipleMethods.call() throws java.lang.Exception
public java.lang.String MultipleMethods.call()

Due to type erasure, the interface Callable has a method java.lang.Object call() and code trying to invoke that method will look for exactly that method only, therefore, a so-called bridge method has been inserted to fulfill the protocol and delegate to the actual implementation method String call(). You can identify bridge methods via Method.isBridge().

The same kind of bridge methods are created when using covariant return types without Generics, as described by this answer. Also, as already said by this answer, class files could have been created by other means than Java source code and since the JVM can handle methods only differing in return type, such methods could appear in such classes without having bridge semantics.

By the way, on the bytecode level, even declared fields are distinguished by name and type, thus, do not need to have unique names if they differ in type. There is no way to generate class files with declared fields of the same name with Java source code, but, as said, that’s not the only way to create class files.

like image 42
Holger Avatar answered Jan 31 '23 12:01

Holger