Java - why no return type based method overloading

2020-01-24 04:15发布

问题:

I know this is not possible but can anyone provide a theory as to why Java chose not to support this? I am asking because I just ran into a situation where I think it would be nice to have.

回答1:

Because you are not required to capture the return value of a method in Java, in which case the compiler can not decide which overload to use. E.g.

boolean doSomething() { ... }

int doSomething() { ... }

doSomething(); // which one to call???


回答2:

One interesting aspect about this question is the fact that the Java language forbids overloading methods only by return type. But not the JVM:

Note that there may be more than one matching method in a class because while the Java language forbids a class to declare multiple methods with the same signature but different return types, the Java virtual machine does not. This increased flexibility in the virtual machine can be used to implement various language features. For example, covariant returns can be implemented with bridge methods; the bridge method and the method being overridden would have the same signature but different return types.

From: Class.getMethod(String, Class...)



回答3:

I've wondered why they don't support this also. Sure, if you ignore the return value, the compiler would have no way to know which you wanted. But that's the same ambiguity that arises with passing nulls. Like:

String doSomething(String s) { ... }
String doSomething(Integer s) { ... }
...
String out=doSomething(null);

In this case, the compiler just complains that the call is ambiguous, and you have to resolve it by casting the null, like:

String out=doSomething((String)null);

You could do the same thing with overloading by return type:

String getSomething() { ... }
Integer getSomething() { ... }
...
Integer n=getSomething();

would presumably call the second function.

getSomething();

would be ambiguous (and in this example, probably useless, unless it had side effects, but that's another story), so you'd have to say:

(String) getSomething();

More realistically, perhaps:

if ((String) getSomething()==null) ...

But that's the easy case. I can see a compiler-writer not wanting to support this because it could get very complicated to figure out in anything other than a simple assignment. For example, consider:

String getSomething() { ... };
Integer getSomething() { ... };
String getOtherthing() { ... };
...
if (getSomething().equals(getOtherthing())) ...

The compiler would have to figure out that both String and Integer have equals functions, so either one is valid at that point. Then it would have to notice that getOtherthing is a String, and Integer.equals(String) is unlikely, so probably what the writer wanted was String.equals(String). Do-able, but at that point I'm starting to see that in the general case, this could be a beast.

And then suppose we add:

Integer getOtherthing() { ... };

Now what does the compiler do with that IF statement? It could use the String versions of both functions, or the Integer, but not the String of one and the Integer of the other. At that point it would have to insist on a cast to tell it which, I guess. But the complexity is really getting out of hand.

And if it's hard for the compiler to figure out what you really mean, imagine what it would be like for another programmer who can't look up all the function signatures as fast as the compiler can.



回答4:

It's because you are free to ignore return value.



回答5:

While it is theoretically possible, it was not used in Java for the same reason it wasn't used in C++; namely, it has been found that overloads based on return-types are generally more confusing to developers, the benefit is marginal compared with the costs of implementing it, and it would be ambiguous in the case where the return-type is not assigned to a value. For those reasons return-type based overloading is not supported.



回答6:

I think one of the reasons is that, in most case you can determine the return type of a function only after the execution of the function instead of before this process. Thus, it can not help you decide which overloaded function to invoke just based on different return types of functions.



回答7:

overloading function only on the basis of return type is confusing for the compiler to distinguish between the calls, because at the time of invocation you are not giving the return type, as in the case with the parameters, so you only give the parameter list and this parameter list is the only way for the compiler to distinguish between the function calls, and return value is received at the completion of the function, that is why return type does not contributes to the signature of the function



回答8:

Method overloading uses compile time polymorphism technique. Method overriding uses run time polymorphism technique.

Method overloading:

As said in previous answers, java does not support method overloading with different return type and same arguments. This is because, it has to determine which method to use at the compile time itself. To remove the ambiguity, they designed the method overloading technique like this.

If we really need method overloading with different types and same arguments, it is possible to some extent with mehtod overriding.

Method overriding:

Method overriding uses run-time polymorphism technique. Hence which method to execute is not decided at compile time and it is decided at run-time by JVM.

With co-variant return types, we can have different return type in the sub class's method with same arguments as base class.

Example of co-variant return type:

            class BaseClass {
                BaseClass dosomething(){
                    System.out.println("Print BaseClass");
                    return this;
                }

            }

            class AnotherBaseClass extends BaseClass {
                @Override
                BaseClass dosomething(){
                    System.out.println("Print AnotherBaseClass");
                    return this;
                }
            }



            class SubClass extends AnotherBaseClass {
                @Override
                SubClass dosomething(){ /*Here SubClass is co-vairantreturn type*/ 
                    System.out.println("Print SubClass");
                    return this;
                }
                public static void main(String args[]){
                  SubClass s1 = new SubClass();
                  s1.dosomething();
                }
            }

Output:

Print SubClass



回答9:

Because Java can cast the return type value to the target variable, so it doesn't know into what variable type are you storing the return value of the function.