关于java:编译语言与口译语言

Compiled vs. Interpreted Languages

我正在努力更好地理解这种差异。我在网上找到了很多解释,但它们倾向于抽象的差异,而不是实际的含义。

我的编程经验大部分都是用cPython(动态的,解释的)和Java(静态的,编译的)。但是,我理解还有其他类型的解释和编译语言。除了可执行文件可以从用编译语言编写的程序中分发之外,每种类型都有什么优点/缺点吗?我经常听到人们争论解释语言可以交互使用,但我相信编译语言也可以有交互实现,对吗?


编译语言是指程序一旦编译,就在目标机器的指令中表达出来的语言。例如,源代码中的加法"+"操作可以直接转换为机器代码中的"加法"指令。

解释语言是指指令不是由目标机器直接执行,而是由其他程序(通常用本机语言编写)读取和执行的语言。例如,解释器在运行时会识别相同的"+"操作,然后解释器用适当的参数调用自己的"add(a,b)"函数,然后执行机器代码"add"指令。

您可以在编译语言的解释语言中做任何事情,反之亦然—它们都是图灵完备的。然而,两者在实现和使用上都有优缺点。

我要完全概括(纯粹主义者原谅我!)但是,大致来说,编译语言的优点如下:

  • 通过直接使用目标计算机的本机代码提高性能
  • 在编译阶段应用相当强大的优化的机会

解释语言的优点如下:

  • 更容易实现(编写好的编译器非常困难!!)
  • 无需运行编译阶段:可以"即时"直接执行代码
  • 可以更方便地使用动态语言

请注意,现代技术(如字节码编译)增加了一些额外的复杂性——这里所发生的是编译器针对的是一个"虚拟机",它与底层硬件不同。然后,这些虚拟机指令可以在以后的阶段重新编译以获得本机代码(例如,Java JVM JIT编译器所做的)。


一种语言本身既不编译也不解释,只有一种语言的特定实现。Java是一个很好的例子。有一个基于字节码的平台(JVM)、一个本地编译器(GCJ)和一个用于Java超集(BSH)的ItPiTe。那么Java是什么呢?字节码编译、本机编译或解释?

其他被编译和解释的语言是scala、haskell或ocaml。每种语言都有一个交互式解释器,以及一个编译到字节的代码或本机代码。

所以一般来说,用"编译的"和"解释的"对语言进行分类没有什么意义。


从A开始思考:从过去开始

很久以前,有一段时间,在计算机领域生活着口译员和编辑。各种各样的纷争接踵而至一个接一个。当时的总体意见是:

  • 解释器:快速开发(编辑和运行)。执行速度慢,因为每个语句都必须解释为每次执行机器代码时(想想这对执行了数千次的循环意味着什么)。
  • 编译器:开发缓慢(编辑、编译、链接和运行)。编译/链接步骤可能需要很长时间)。快的执行。整个程序已经在本机代码中了。

运行时的一个或两个数量级差异解释程序和编译程序之间存在性能。其他区别例如,代码的运行时可变性点也引起了一些兴趣,但主要是区别在于运行时性能问题。

今天,景观的发展到了这样一个程度,编译/解释的区别是相当不相关。许多编译语言调用的运行时服务不是完全基于机器代码。而且,大多数解释语言都被"编译"成字节码。执行前。字节码解释器非常有效,可以与某些编译器生成的解释器相媲美。从执行速度的角度来看代码。

典型的区别是编译器生成本机代码,解释器读取源代码和使用某种运行时系统动态生成机器代码。如今,几乎所有的经典口译员都已不复存在。编译成字节码(或其他半编译状态),然后在虚拟"机器"上运行。


极端和简单的情况:

  • 编译器将以目标计算机的本机可执行格式生成二进制可执行文件。这个二进制文件包含除系统库之外的所有必需资源;它可以在没有进一步准备和处理的情况下运行,并且运行起来像闪电一样,因为代码是目标计算机上CPU的本机代码。

  • 解释器将在用户可以输入语句或代码的循环中向用户提供一个提示,当点击RUN或等效工具时,解释器将检查、扫描、分析并解释地执行每一行,直到程序运行到停止点或错误为止。因为每一行都是单独处理的,而且口译员没有从以前看到的行中"学习"任何东西,所以每一行每次都要努力将人类可读的语言转换为机器指令,所以速度很慢。从好的方面来说,用户可以通过各种方式检查和交互程序:更改变量、更改代码、在跟踪或调试模式下运行…无论什么。

有了这些障碍,让我来解释一下,生活不再那么简单了。例如,

  • 许多口译员会预先编译他们所给的代码,这样翻译步骤就不必反复重复了。
  • 有些编译器编译的不是CPU特定的机器指令,而是字节码,一种虚拟机器的人工机器代码。这使得编译后的程序更易于移植,但在每个目标系统上都需要一个字节码解释器。
  • 字节码解释器(我在这里看Java)最近倾向于重新编译它们在执行之前被获取给目标部分的CPU的字节码(称为JIT)。为了节省时间,通常只对经常运行的代码(热点)执行此操作。
  • 一些看起来和行为类似于解释器的系统(例如clojure)会立即编译他们得到的任何代码,但允许交互访问程序的环境。这基本上就是译员使用二进制编译速度的便利性。
  • 有些编译器并不真正编译,它们只是预消化和压缩代码。我听说过Perl就是这样工作的。所以有时候编译器只是做了一点工作,而大部分工作仍然是解释。

最后,这些天,解释与编译是一种权衡,编译花费的时间(一次)通常会得到更好的运行时性能,但解释环境会给交互提供更多的机会。编译和解释主要是关于如何在不同的过程中划分程序的"理解"工作的问题,而随着语言和产品试图提供两个世界中最好的语言和产品,这条线现在有点模糊。


来自http://www.quora.com/what-is-the-difference-between-compiled-and-explocated-programming-languages

There is no difference, because"compiled programming language" and
"interpreted programming language" aren’t meaningful concepts. Any
programming language, and I really mean any, can be interpreted or
compiled. Thus, interpretation and compilation are implementation
techniques, not attributes of languages.

Interpretation is a technique whereby another program, the
interpreter, performs operations on behalf of the program being
interpreted in order to run it. If you can imagine reading a program
and doing what it says to do step-by-step, say on a piece of scratch
paper, that’s just what an interpreter does as well. A common reason
to interpret a program is that interpreters are relatively easy to
write. Another reason is that an interpreter can monitor what a
program tries to do as it runs, to enforce a policy, say, for
security.

Compilation is a technique whereby a program written in one language
(the"source language") is translated into a program in another
language (the"object language"), which hopefully means the same thing
as the original program. While doing the translation, it is common for
the compiler to also try to transform the program in ways that will
make the object program faster (without changing its meaning!). A
common reason to compile a program is that there’s some good way to
run programs in the object language quickly and without the overhead
of interpreting the source language along the way.

You may have guessed, based on the above definitions, that these two
implementation techniques are not mutually exclusive, and may even be
complementary. Traditionally, the object language of a compiler was
machine code or something similar, which refers to any number of
programming languages understood by particular computer CPUs. The
machine code would then run"on the metal" (though one might see, if
one looks closely enough, that the"metal" works a lot like an
interpreter). Today, however, it’s very common to use a compiler to
generate object code that is meant to be interpreted—for example, this
is how Java used to (and sometimes still does) work. There are
compilers that translate other languages to JavaScript, which is then
often run in a web browser, which might interpret the JavaScript, or
compile it a virtual machine or native code. We also have interpreters
for machine code, which can be used to emulate one kind of hardware on
another. Or, one might use a compiler to generate object code that is
then the source code for another compiler, which might even compile
code in memory just in time for it to run, which in turn . . . you get
the idea. There are many ways to combine these concepts.


解释源代码相对于编译源代码的最大优势是可移植性。

如果编译了源代码,则需要为要运行程序的每种类型的处理器和/或平台(例如,一种用于Windows x86,一种用于Windows x64,一种用于Linux x64,等等)编译不同的可执行文件。此外,除非您的代码完全符合标准,并且不使用任何平台特定的功能/库,否则您实际上需要编写和维护多个代码基!

如果您的源代码被解释了,您只需要编写一次,并且它可以被任何平台上的适当的解释程序解释和执行!它是便携式的!请注意,解释器本身是为特定平台编写和编译的可执行程序。

编译代码的一个优点是它对最终用户隐藏源代码(这可能是知识产权),因为您部署的不是原始的人类可读源代码,而是一个模糊的二进制可执行文件。


编译器和解释器做同样的工作:将一种编程语言翻译成另一种PGORaming语言,通常更接近硬件,通常是直接可执行的机器代码。

传统上,"编译"意味着这种转换一次完成,由开发人员完成,生成的可执行文件分发给用户。纯示例:C++。编译通常需要相当长的时间,并尝试执行大量昂贵的optmation,以便生成的可执行文件运行得更快。最终用户没有自己编译东西的工具和知识,并且可执行文件通常必须在各种硬件上运行,因此不能进行许多特定于硬件的优化。在开发过程中,单独的编译步骤意味着更长的反馈周期。

传统上,"解释"意味着当用户想要运行程序时,翻译会"即时"进行。纯示例:香草PHP。一个幼稚的解释器每次运行时都必须解析和翻译每一段代码,这使得它非常慢。它不能进行复杂的、代价高昂的优化,因为它们比执行时节省的时间要长。但是它可以充分利用它运行的硬件的功能。缺少单独的编译步骤可以减少开发期间的反馈时间。

但如今,"编译与解释"并不是一个黑白的问题,两者之间存在着阴影。天真、简单的口译员几乎灭绝了。许多语言都使用两步流程,将高级代码转换为独立于平台的字节码(这样解释起来要快得多)。然后,您有"实时编译器",每个程序运行最多编译一次代码,有时缓存结果,甚至智能地决定解释很少运行的代码,并对运行很多的代码进行强大的优化。在开发过程中,调试程序能够在运行的程序中切换代码,即使对于传统的编译语言也是如此。


首先,一个澄清,Java不是完全静态编译和链接的方式C++。它被编译成字节码,然后由JVM解释。JVM可以对本机语言进行及时编译,但不必这样做。

更重要的是:我认为互动性是主要的实际区别。由于所有内容都被解释了,所以您可以从代码中摘录一小部分,然后根据环境的当前状态进行分析和运行。因此,如果您已经执行了初始化变量的代码,那么您就可以访问该变量等。它确实为函数样式这样的事情提供了自己的途径。

然而,解释要花费很多,特别是当你有一个包含大量引用和上下文的大型系统时。根据定义,这是浪费的,因为相同的代码可能需要解释和优化两次(尽管大多数运行时对此都有一些缓存和优化)。不过,您需要支付运行时成本,并且经常需要运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能没有充分的交互作用。

因此,对于不会发生太大变化的大型系统,对于某些语言,预编译和预链接所有内容更有意义,可以执行所有可以执行的优化。最后是一个非常精简的运行时,它已经针对目标机器进行了优化。

至于生成可执行文件,这与它无关,imho。通常可以从编译语言创建可执行文件。但也可以从解释语言创建可执行文件,除非解释器和运行时已经打包在可执行文件中,并且对您隐藏。这意味着您通常仍然要支付运行时成本(尽管我确信对于某些语言,有一些方法可以将所有内容转换为树可执行文件)。

我不同意所有的语言都可以交互。某些语言,如C,与机器和整个链接结构联系在一起,我不确定您是否可以构建一个有意义的、完全成熟的交互版本。


Python书?2015想象出版有限公司,简单地通过第10页中提到的以下提示来消除差异:

An interpreted language such as Python is one where the source code is converted to machine code and then executed each time the program runs. This is different from a compiled language such as C, where the source code is only converted to machine code once – the resulting machine code is then executed each time the program runs.


很难给出一个实际的答案,因为不同之处在于语言定义本身。可以为每种编译语言构建解释程序,但不可能为每种解释语言构建编译器。这与语言的正式定义有关。所以,理论信息学的东西在大学里是不受欢迎的。


编译是从用编译的编程语言编写的代码创建可执行程序的过程。编译允许计算机运行和理解程序,而不需要用于创建程序的编程软件。当一个程序被编译时,它通常是为一个特定的平台(如IBM平台)编译的,该平台与IBM兼容的计算机一起工作,而不是其他平台(如苹果平台)。第一个编译器是由GraceHopper在哈佛MarkI计算机上开发的。今天,大多数高级语言都将包含自己的编译器,或者提供可用于编译程序的工具包。使用Java的编译器的一个很好的例子是Eclipse,一个用C和C++使用的编译器的例子是GCC命令。根据程序的大小,编译需要几秒钟或几分钟,如果编译时没有遇到错误,则会创建一个可执行文件。请检查此信息。


差异

解释器:

1)过程:解释器从程序中产生结果。(程序运行时将程序转换为机器代码)在解释程序中,另一方面,源代码通常是程序。这种类型的程序(通常称为脚本)需要一个解释器,解释器解析程序中的命令,然后执行它们。一些解释器,如unix shell(sh、csh、ksh等),读取并立即执行每个命令,而其他解释器,如perl,在发送相应的机器语言指令之前分析整个脚本。解释语言的其他示例包括javascript和python。

2)快速开发(编辑和运行)。

3)执行速度慢,因为每次执行语句时都必须将其解释为机器代码(想想这对于执行了数千次的循环意味着什么)。

4)如果您的源代码被解释了,您只需要写一次,它可以被任何平台上的适当的解释程序解释和执行!

5)使用解释器的一个缺点是它不会向最终用户隐藏源代码。

6)继续翻译程序,直到遇到第一个错误,在这种情况下,程序停止。因此调试很容易。

编译程序:

1)进程:(在程序运行之前将程序转换为机器代码),而编译器生成用汇编语言编写的程序。然后,体系结构的汇编程序将生成的程序转换成二进制代码。汇编语言因每台计算机的结构而异。因此,编译的程序只能在与编译它们的计算机具有相同体系结构的计算机上运行。编译的程序不是人类可读的,而是使用特定于体系结构的机器语言。创建编译程序需要几个步骤。首先,程序员使用开发工具甚至简单的文本编辑器,用选定的计算机语言编写源代码。如果程序很复杂,那么它的各个部分可能会分布在多个文件中。然后,程序员编译程序,对模块进行排序和链接,并将它们全部翻译成计算机能理解的机器代码。因为不同类型的计算机不能互相说机器语言,所以编译后的程序只能在它设计的平台上工作。例如,为HP-UX编写的程序通常无法在Mac OS计算机或运行Solaris的计算机上运行。

2)开发(编辑、编译、链接和运行)缓慢。编译/链接步骤可能需要很长时间)。

3)执行速度快。整个程序已经在本机代码中了。

4)编译后的程序只能在它设计的平台上运行。它不便携

5)编译代码的一个优点是它对最终用户隐藏源代码(这可能是知识产权),因为您部署的不是最初的人类可读源代码,而是一个模糊的二进制可执行文件。6)扫描整个程序后才产生错误信息。因此调试比较困难。

资料来源:*网址:https://kb.iu.edu/d/agsz*这篇文章的答案不一样