为什么C需要原型函数而Java不需要?

我参加了Java课程,并试图用K&R教我自己。 到目前为止这么好,但我不明白原型的目的。 请参阅以下代码中的2 //评论:

#include  float convert(int); **//Why is this needed...** main() { int i; for(i = 0; i <= 300; i += 20) printf("F: %3d C: %6.1f\n",i,convert(i)); system("Pause"); return 0; } float convert(int f) **//When we already have this?** { float c = (5.0/9.0) * (f-32.0); return c; } 

在Java中,您将声明一个类似于public static float convert(int f)而根本不需要原型。 这对我来说似乎更简单。 为什么不同?

这基本上是为语言系统做出的决定。

请注意,Java和C编译器都需要知道函数签名,以便它们可以进行类型检查,并编译代码。

另请注意,像C这样的语言需要您单独提供此签名/原型(在声明中),而实际上函数定义具有完全相同的信息。 所以,它基本上是信息的重复。 为什么是这样? 从本质上讲,这样可以在没有包含定义的实际源代码的情况下编译代码。 因此,如果一个库是作为二进制代码提供的,那么拥有包含原型的头文件就足以允许编译使用库中代码的其他代码。

Java和C#等更现代的语言不需要重复这些原型信息。 当他们确实需要原型时,他们如何编译代码? 他们所做的是在处理定义时将原型信息与二进制代码一起存储。 所以,实际上,原型信息只是由编译器本身自动生成的。

Java编译器可以通过它的名称和包找到一个类,并直接检查源代码。 注意:如果Java编译器不能这样做,它将无法编译。

在C中,对于您可以放置​​哪些定义没有限制,因此您必须首先让它知道您稍后可能定义的内容。

在C中,标识符通常必须在可以使用之前声明。 函数原型用作函数的声明。 C是一种古老的语言,迫使程序员声明函数标识符有助于编译器/链接器的编程,特别是当函数在不同的转换单元中使用和定义时。

C和Java都在编译时检查函数调用是否与函数签名匹配。

AC编译器总是依赖源代码中的函数声明/原型。 函数声明必须出现在调用之前。

Java编译器可以从以下位置获取函数声明:

  • 在同一顶级课程中的任何地方。 函数定义不必放在所有调用之上。
  • 来自另一个类的源代码或已编译的* .class文件。 完全限定的类名允许在类路径中找到* .class文件。