Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么方法签名中不包括方法的返回类型?_Java - Fatal编程技术网

Java 为什么方法签名中不包括方法的返回类型?

Java 为什么方法签名中不包括方法的返回类型?,java,Java,为什么签名中不包括方法的返回类型 一个例子 public void method1(String arg){...} public String method1(String arg){...} 这将导致一个错误 不能仅在方法的返回类型上重载该方法。这完全是违法的。让我们假设使用返回类型重载方法是合法的,您定义了两个method1方法。现在我们要调用返回字符串对象的函数: 字符串=方法1(某事物) 从理论上讲,JVM能够识别您指定调用的方法,但是这种调用又如何呢 方法1(某事物) 正如您所看

为什么签名中不包括方法的返回类型

一个例子

public void method1(String arg){...}

public String method1(String arg){...}

这将导致一个错误

不能仅在方法的返回类型上重载该方法。这完全是违法的。让我们假设使用返回类型重载方法是合法的,您定义了两个
method1
方法。现在我们要调用返回
字符串对象的函数

字符串=方法1(某事物)

从理论上讲,JVM能够识别您指定调用的方法,但是这种调用又如何呢

方法1(某事物)


正如您所看到的,这两种方法都可以被调用,并且这样的操作是明确的。JVM不知道应该调用哪个方法。这就是为什么禁止这种重载。

之所以这样做,是因为编译器无法在所有上下文中找出重载

例如,如果你打电话

String x = method1("aaa");
method1("aaa");
编译器知道您正在寻找第二个重载。然而,如果你打电话

String x = method1("aaa");
method1("aaa");

这样,编译器就不知道要调用两个方法中的哪一个,因为调用返回
String
的方法并放弃结果是可以的。为了避免这样的歧义,Java禁止只在返回类型上不同的重载。

您可以将函数作为过程调用:
method1(“arg”)
其中method1是列表中的第二个方法(
stringmethod1(stringarg){}
)。编译器将无法将其与第一个方法区分开来(
void method1(String arg){}
)。

因为在这种情况下,无法确定应该调用哪些重载方法:

public static void main(String... args) {
    method1("aaa");
}

方法重载是根据参数的数量和类型而不是返回类型来检查的。这就是为什么会出现错误。

因为你的问题在标题中没有提到任何特定的编程语言(我知道它在标签中有提到),所以我将与Swift分享我最近的经验。 在Swift中,函数/方法签名实际上包括返回类型。因此,只有在调用此函数/方法而未显式指定返回类型时,编译器才会抛出错误,例如:

func some() -> Bool {
    return true;
}

func some() -> Int {
    return 1;
}

let valBool: Bool = some()
let valInt: Int = some()

// this doesn't work: Ambiguous use of 'some'
some()
除此之外,Swift还使它更有趣。仅当参数名称不同时,它允许您有两个具有相同参数和返回类型的函数/方法,例如:

func some(#foo: Bool) -> Bool {
    return foo;
}

func some(#bar: Bool) -> Bool {
    return bar;
}

some(foo: true)
some(bar: false)
因此,它在签名方法中为您提供了语义差异

UPD。由于Swift 2.0外部参数名称已更改,现在您必须提供两次外部和本地名称,即使它们相同

func some(foo foo: Bool) -> Bool {
    return foo;
}

func some(bar bar: Bool) -> Bool {
    return bar;
}

some(foo: true)
some(bar: false)

当设计过载解决方案时,有几点需要考虑。

忽略返回类型重载的原因:

  • 简化忽略函数返回值(就像人们经常处理错误代码一样)
  • 使程序更容易为人类读者理解。特别是,这就是Python中根本没有函数重载的原因。(品味问题)
  • C遗产。当语言来自C族,设计师不认为某事是一件大事时,它就永远是……/LI>。 在返回类型上添加重载的原因:

  • 使忽略返回值变得困难。这可能很方便,也节省了一些打字时间,但总有一天会让你头疼的
  • 表达性(当然,与易于消化相反:)。你有没有想过写一些东西,比如
    intx=json.get(“int_值”);float y=json.get(“float_值”)?在某些语言(如C++)中,仍然可以通过代理和强制转换运算符来实现,但返回类型的重载要容易得多
  • 表现力。每次您传递retun值作为对函数的引用只是为了重用其资源,这可能是返回类型的重载(带有类似隐藏参数)。考虑<代码>字符串S;getline(cin,s),vs
    字符串s=getline(cin)。这就是表达性与引用透明性结合在一起的地方,最终是易于代码消化的地方

  • 现在回到你的问题“为什么?”。既然您问的是Java,答案显然是因为James重视省略返回类型重载的原因,而不是在语言中包含它们的原因。

    编译器负责方法绑定。当遇到methodName()时,它必须绑定到某个方法定义,此时它可能不知道方法的返回类型。因此,方法签名中不包括方法返回类型。编译器根据方法签名绑定方法。

    我自己也曾有过同样的问题,虽然我可以看出,如果不将返回值赋给适当类型的变量,编译器将不知道调用哪个函数,但为什么要在函数级别抛出错误呢?为什么不在调用函数的时候呢?基本上,一旦您承诺让签名只在返回值上有所不同,就要由您来确保以这种方式使用它们,然后,也只有到那时,编译器才会抱怨。当然,可能需要一些额外的工作才能使用严格的单通道编译器,但我认为它可以运行。

    你不能,因为你不能?真的吗?我在编辑中解释过;)我之所以提交这篇短文,是因为为这些简单的问题写答案就像一场竞赛,所以如果你能取消你的否决票,我告诉过你为什么这是被禁止的,这样的代码无法编译。最大的问题是执行这样明确的代码,因此语言规范规定不允许这样的构造。因为这是试图定义具有相同签名的两个methode。这在methode表中被检查,是不允许的。因为当编译器在类中找到具有相同签名的两个methode定义时无法区分methode表中保存的是哪一个