Java - Why No Return Type Based Method Overloading

Java - why no return type based method overloading?

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???

Why is the return type not considered when differentiating methods?

Because it's not required to assign the result when you want to execute a method. How would the compiler then know which of the overloaded ones you'd like to call? There will be ambiguity.

Does Java virtual machine allow overloading on return type?

These statements are perfectly true.

Remember that Java is two things - one,a language and two, a virtual machine. While restricting the language to not allow type based method overloading makes Java a simpler language to use, the JVM can still allow this to be done to make it more powerful.

As a language, Java has a compiler that enforces the rules that make Java a simpler, easier programming language than one that does allow this. To do this, it restricts what you can do, but only in the Java language itself. Running something like Scala or Ruby on the JVM requires different rules and features, and at this level it is important that the JVM allows the flexibility that has made the JVM such a big success that it is found on so many platforms and devices.

In a language where overloading by return type is possible, it would be very error prone and the decision to not support that feature was deliberate to make Java a less error-prone programming language. How would the compiler know which function you intended to call?

The JVM on the other hand is a low-level, highly optimised virtual machine that exists to run bytecode, not Java. It is therefore not wise to restrict the JVM in this fashion as it should be able to run bytecode not generated from Java at all.

Another example would be multiple inheritance, which is not available in Java, yet nothing prevents you to write a language that supports multiple inheritance and have it compile to bytecode. It would make your language more difficult to use and potentially more error prone, but if you require that feature, the JVM will not stop you.

Overload with different return type in Java?

You can't do it in Java, and you can't do it in C++. The rationale is that the return value alone is not sufficient for the compiler to figure out which function to call:

public int foo() {...}
public float foo() {..}

...
foo(); // which one?

Why is method overloading not defined for different return types?

You can of course have overloading for methods which differ by return type, just not for methods which differ only by return type. For example, this is fine:

def foo(s: String) : String = s + "Hello"
def foo(i: Int) : Int = i + 1

That aside, the answer to your question is evidently that it was a design decision: the return type is part of the method signature as anyone who has experienced an AbstractMethodError can tell you.

Consider however how allowing such overloading might work in tandem with sub-typing:

class A {
def foo: Int = 1
}
val a: A = //...lookup an A
val b = a.foo

This is perfectly valid code of course and javac would uniquely resolve the method call. But what if I subclass A as follows:

class B extends A {
def foo: String = "Hello"
}

This causes the original code's resolution of which method is being called to be broken. What should b be? I have logically broken some existing code by subtyping some existing class, even though I have not changed either that code or that class.

why java compiler can't decide which method to call based on return type

You're looking at the compiled code, i.e. you're assuming the compiler can decide which method to compile. But the problem is it can't (for the same reason in the answer to the mentioned post). The compiler does not read bytecode, it produces it. What reads the bytecode is the JVM.

Don't confuse between defining the methods and using them. Technically you can define both

int foo()
void foo()

But then imagine someone just calls foo() in his/her code without possibly assigning the return value to a variable. How would the compiler know the call to which method to place in the compiled code?

Why is the return type of method not included in the method-signature?

This is done because the compiler would not be able to figure out the overload in all contexts.

For example, if you call

String x = method1("aaa");

the compiler knows that you are looking for the second overload. However, if you call

method1("aaa");

like this, the compiler has no idea which one of the two methods you wanted to invoke, because it is OK to call a method returning String and discard the result. To avoid ambiguities like this, Java prohibits overloads that differ solely on the return type.

The relationship of overload and method return type in Java?

consider following points for overloading:

  1. First and important rule to overload a method in java is to change method signature. Method signature is made of number of arguments, type of arguments and order of arguments if they are of different types.

    public class DemoClass {
    // Overloaded method
    public Integer sum(Integer a, Integer b) {
    return a + b;
    }

    // Overloading method
    public Integer sum(Float a, Integer b) { //Valid
    return null;
    }
    }
  2. Return type of method is never part of method signature, so only changing the return type of method does not amount to method overloading.

    public class DemoClass {
    // Overloaded method
    public Integer sum(Integer a, Integer b) {
    return a + b;
    }

    // Overloading method
    public Float sum(Integer a, Integer b) { //Not valid; Compile time error
    return null;
    }
    }
  3. Thrown exceptions from methods are also not considered when overloading a method. So your overloaded method throws the same exception, a different exception or it simply does no throw any exception; no effect at all on method loading.

    public class DemoClass {
    // Overloaded method
    public Integer sum(Integer a, Integer b) throws NullPointerException{
    return a + b;
    }

    // Overloading method
    public Integer sum(Integer a, Integer b) throws Exception{ //Not valid; Compile time error
    return null;
    }
    }


Related Topics



Leave a reply



Submit