More than one method with the same parameter types

2019-06-16 21:57发布

I know, there is already at least one question on this topic. But I want to ask it again because this is what I discovered in the javadoc of Class#getDeclaredMethod(...):

If more than one method with the same parameter types is declared in a class, and one of these methods has a return type that is more specific than any of the others, that method is returned; otherwise one of the methods is chosen arbitrarily.

So the developers of the reflection in java consider that case as a probable one, is it maybe possible after all to do such declaration? Or is it maybe just deprecated?

1条回答
【Aperson】
2楼-- · 2019-06-16 22:05

The JVM bytecode format permits the declaration of multiple methods with the same name and the same parameter types as long as the return type differs, although the Java language does not permit this. This means a) other JVM languages can make use of this and b) it can be used for special "compiler-magic" language features.

Most commonly, the compiler emits multiple methods with the same name and the same parameter types when dealing with generics. JVM method lookup relies on the entire signature to match, not just the parameter types. Thus, the compiler has to emit so-called bridge methods that override or shadow other methods signature-wise. Consider this example:

interface Foo<T>
{
    T foo(); // desc: ()Ljava/lang/Object;

    void bar(T value); // desc: (Ljava/lang/Object;)V

    Object baz(); // desc: ()Ljava/lang/Object;
}

class StringFoo implements Foo<String>
{
    @Override
    public String foo() { ... } // desc: ()Ljava/lang/String; // !

    @Override
    public void bar(String value) { ... } // desc: (Ljava/lang/String;)V // !

    @Override
    public String baz() { ... } // desc: ()Ljava/lang/String; // !
}

The StringFoo class needs three additional bridge methods to actually override the interface methods in terms of having the same desc:

class StringFoo implements Foo<String>
{
    public String foo() { ... }

    public /* synthetic bridge */ Object foo() // desc: ()Ljava/lang/Object;
    {
        return /* String */ foo(); // statically linked to String foo()
    }

    public void bar(String value) { ... }

    public /* synthetic bridge */ void bar(Object value) // desc: (Ljava/lang/Object;)
    {
        return bar((String) value);
    }

    public String baz() { ... }

    public /* synthetic bridge */ Object baz() // desc: ()Ljava/lang/Object;
    {
        return /* String */ baz(); // statically linked to String baz()
    }
}

The pseudo-modifiers synthetic bridge are two JVM access flags that are only used by the compiler to mark auto-generated methods in the bytecode

The Class#getDeclaredMethods method returns all declared methods - including synthetic bridge methods. Thus, #getDeclaredMethod(String) has to pick one that is the actual implementation.

查看更多
登录 后发表回答