【发布时间】:2011-02-14 05:30:14
【问题描述】:
我知道这是不可能的,但是谁能提供一个理论来解释为什么 Java 选择不支持这个?我之所以问,是因为我刚刚遇到了一种情况,我认为拥有它会很好。
【问题讨论】:
标签: java programming-languages return overloading
我知道这是不可能的,但是谁能提供一个理论来解释为什么 Java 选择不支持这个?我之所以问,是因为我刚刚遇到了一种情况,我认为拥有它会很好。
【问题讨论】:
标签: java programming-languages return overloading
因为在 Java 中不需要捕获方法的返回值,在这种情况下编译器无法决定使用哪个重载。例如
boolean doSomething() { ... }
int doSomething() { ... }
doSomething(); // which one to call???
【讨论】:
关于这个问题的一个有趣的方面是 Java 语言禁止仅通过返回类型重载方法。但不是 JVM:
注意可能不止一个 类中的匹配方法,因为 而 Java 语言禁止 声明多个方法的类 相同的签名但不同 返回类型,Java 虚拟机 才不是。这增加了灵活性 在虚拟机中可以用来 实现各种语言功能。 例如,协变收益可以是 用桥接方法实现;这 桥接法和方法是 覆盖将具有相同的 签名,但返回类型不同。
【讨论】:
我想知道为什么他们也不支持这一点。当然,如果您忽略返回值,编译器将无法知道您想要哪个。但这与传递空值产生的歧义相同。喜欢:
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 都具有 equals 函数,因此此时任何一个都有效。然后它必须注意到 getOtherthing 是一个字符串,而 Integer.equals(String) 不太可能,所以作者想要的可能是 String.equals(String)。可行,但那时我开始看到,在一般情况下,这可能是一头野兽。
然后假设我们添加:
Integer getOtherthing() { ... };
现在编译器对该 IF 语句做了什么?它可以使用两个函数的字符串版本,或整数,但不能使用一个函数的字符串和另一个函数的整数。到那时,我猜它必须坚持演员才能告诉它。但复杂性真的失控了。
如果编译器很难弄清楚你的真正意思,想象一下对于无法像编译器一样快地查找所有函数签名的另一个程序员会是什么样子。
【讨论】:
void 的二级重载 - 如果它会被完全忽略。在将返回值作为参数传递给其他函数的情况下,不会考虑二次重载。我认为这样的规则会避免歧义,同时允许一些有用的优化。
这是因为你可以随意忽略返回值。
【讨论】:
虽然理论上是可行的,但它并没有在 Java 中使用,原因与它没有在 C++ 中使用的原因相同;也就是说,已经发现基于返回类型的重载通常更容易让开发人员感到困惑,与实现它的成本相比,收益是微不足道的,并且在没有将返回类型分配给价值。由于这些原因,不支持基于返回类型的重载。
【讨论】:
我认为原因之一是,在大多数情况下,您只能在函数执行之后而不是在此过程之前确定函数的返回类型。因此,仅根据函数的返回类型不同,无法帮助您决定调用哪个重载函数。
【讨论】:
仅根据返回类型重载函数会使编译器混淆调用之间的区别,因为在调用时您没有给出返回类型,就像参数的情况一样,所以您只给出参数列表和这个参数列表是编译器区分函数调用的唯一方法,并且在函数完成时接收返回值,这就是为什么返回类型对函数的签名没有贡献
【讨论】:
方法重载使用编译时多态技术。 方法覆盖使用运行时多态技术。
方法重载:
正如前面的答案所说,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();
}
}
输出:
打印子类
【讨论】:
因为Java可以将返回类型值强制转换为目标变量,所以它不知道你将函数的返回值存储成什么变量类型。
【讨论】: