Java - 为什么没有基于返回类型的方法重载?

时间:2010-04-30 12:36:59

标签: java programming-languages return overloading

我知道这是不可能的,但任何人都可以提供一个理论,为什么Java选择不支持这个?我问的是因为我遇到了一个我认为会很好的情况。

9 个答案:

答案 0 :(得分:75)

因为您不需要在Java中捕获方法的返回值,在这种情况下,编译器无法决定使用哪个重载。 E.g。

boolean doSomething() { ... }

int doSomething() { ... }

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

答案 1 :(得分:31)

关于这个问题的一个有趣的方面是Java语言仅禁止通过返回类型重载方法。但不是JVM:

  

请注意,可能不止一个   因为类中的匹配方法   而Java语言禁止使用   用于声明多个方法的类   相同的签名但不同   返回类型,Java虚拟机   才不是。这增加了灵活性   在虚拟机中可以用来   实现各种语言功能。   例如,协变返回可以是   用桥接方法实现;该   桥接方法和方法   被覆盖的也是一样的   签名但不同的退货类型。

来自:Class.getMethod(String, Class...)

答案 2 :(得分:13)

我想知道为什么他们也不支持这个。当然,如果忽略返回值,编译器将无法知道您想要的是什么。但这与传递空值时产生的模糊性相同。像:

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

在这种情况下,编译器只是抱怨调用是不明确的,你必须通过转换null来解决它,如:

String out=doSomething((String)null);

你可以通过返回类型重载:

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

可能会调用第二个函数。

getSomething();

会模棱两可(在这个例子中,可能没用,除非它有副作用,但这是另一个故事),所以你不得不说:

(String) getSomething();

更现实地说,或许:

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

但这很简单。我可以看到一个编译器 - 编写器不想支持它,因为除了简单的赋值之外,它可能会变得非常复杂。例如,考虑:

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

编译器必须弄清楚String和Integer都有等于函数,因此在这一点上任何一个都是有效的。然后它必须注意到getOtherthing是一个String,并且Integer.equals(String)不太可能,因此作者想要的可能是String.equals(String)。可行,但在那时我开始看到,在一般情况下,这可能是一头野兽。

然后假设我们添加:

Integer getOtherthing() { ... };

现在编译器对IF语句做了什么?它可以使用两个函数的String版本,也可以使用Integer,但不能使用一个String和另一个的Integer。在那时,它必须坚持要一个演员告诉它,我猜。但复杂性真的失控了。

如果编译器很难弄清楚你的真正含义,想象一下那些无法像编译器那样快速查找所有函数签名的程序员会是什么样子。

答案 3 :(得分:3)

这是因为你可以自由地忽略返回值。

答案 4 :(得分:3)

虽然理论上可行,但它没有在Java中使用,原因与它在C ++中没有使用的原因相同;也就是说,已经发现基于返回类型的重载通常对开发人员来说更加混乱,与实现它的成本相比,其好处是微不足道的,并且在返回类型未分配给a的情况下它将是模糊的。值。由于这些原因,不支持基于返回类型的重载。

答案 5 :(得分:1)

我认为其中一个原因是,在大多数情况下,只有在执行函数之后才能确定函数的返回类型,而不是在此过程之前。因此,它无法帮助您根据不同的函数返回类型决定调用哪个重载函数。

答案 6 :(得分:0)

仅在返回类型的基础上重载函数让编译器难以区分调用,因为在调用时你没有给出返回类型,如参数的情况,所以你只给出参数列表和这个参数列表是编译器区分函数调用的唯一方法,并且在函数完成时接收返回值,这就是为什么返回类型不对函数的签名做出贡献

答案 7 :(得分:0)

方法重载使用编译时多态技术。 方法覆盖使用运行时多态技术。

方法重载:

如先前的回答所述,java不支持具有不同返回类型和相同参数的方法重载。这是因为,它必须确定在编译时本身使用哪种方法。为了消除歧义,他们设计了这样的方法重载技术。

如果我们确实需要使用不同类型和相同参数的方法重载,则在某种程度上可以使用方法重载。

方法替代:

方法覆盖使用运行时多态技术。因此,执行哪种方法不是在编译时决定的,而是在运行时由JVM决定的。

对于协变返回类型,子类的方法中可以具有与基类相同的参数的不同返回类型。

协变量返回类型的示例:

            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();
                }
            }

输出:

打印子类

答案 8 :(得分:-2)

因为Java可以将返回类型值强制转换为目标变量,所以它不知道存储函数返回值的变量类型。