Java 编译语言与解释语言

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3265357/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 19:08:46  来源:igfitidea点击:

Compiled vs. Interpreted Languages

javapythoncompiler-constructionprogramming-languagesinterpreter

提问by chimeracoder

I'm trying to get a better understanding of the difference. I've found a lot of explanations online, but they tend towards the abstract differences rather than the practical implications.

我试图更好地了解差异。我在网上找到了很多解释,但它们倾向于抽象差异而不是实际含义。

Most of my programming experiences has been with CPython (dynamic, interpreted), and Java (static, compiled). However, I understand that there are other kinds of interpreted and compiled languages. Aside from the fact that executable files can be distributed from programs written in compiled languages, are there any advantages/disadvantages to each type? Oftentimes, I hear people arguing that interpreted languages can be used interactively, but I believe that compiled languages can have interactive implementations as well, correct?

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

采纳答案by mikera

A compiled language is one where the program, once compiled, is expressed in the instructions of the target machine. For example, an addition "+" operation in your source code could be translated directly to the "ADD" instruction in machine code.

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

An interpreted language is one where the instructions are not directly executed by the target machine, but instead read and executed by some other program (which normally iswritten in the language of the native machine). For example, the same "+" operation would be recognised by the interpreter at run time, which would then call its own "add(a,b)" function with the appropriate arguments, which would then execute the machine code "ADD" instruction.

一种解释语言是其中所述指令不被目标机器直接执行,而是读取和执行通过一些其它方案(其通常写入本机机器的语言)。例如,解释器会在运行时识别相同的“+”操作,然后它会使用适当的参数调用自己的“add(a,b)”函数,然后执行机器代码“ADD”指令.

You can do anything that you can do in an interpreted language in a compiled language and vice-versa - they are both Turing complete. Both however have advantages and disadvantages for implementation and use.

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

I'm going to completely generalise (purists forgive me!) but, roughly, here are the advantages of compiled languages:

我将完全概括(纯粹主义者原谅我!)但是,粗略地说,以下是编译语言的优点:

  • Faster performance by directly using the native code of the target machine
  • Opportunity to apply quite powerful optimisations during the compile stage
  • 直接使用目标机器的本机代码实现更快的性能
  • 在编译阶段应用非常强大的优化的机会

And here are the advantages of interpreted languages:

以下是解释型语言的优点:

  • Easier to implement (writing good compilers is very hard!!)
  • No need to run a compilation stage: can execute code directly "on the fly"
  • Can be more convenient for dynamic languages
  • 更容易实现(编写好的编译器非常困难!!)
  • 无需运行编译阶段:可以直接“即时”执行代码
  • 对于动态语言可以更方便

Note that modern techniques such as bytecode compilation add some extra complexity - what happens here is that the compiler targets a "virtual machine" which is not the same as the underlying hardware. These virtual machine instructions can then be compiled again at a later stage to get native code (e.g. as done by the Java JVM JIT compiler).

请注意,字节码编译等现代技术增加了一些额外的复杂性——这里发生的情况是编译器针对的是与底层硬件不同的“虚拟机”。这些虚拟机指令然后可以在稍后阶段再次编译以获得本机代码(例如,由 Java JVM JIT 编译器完成)。

回答by Uri

First, a clarification, Java is not fully static-compiled and linked in the way C++. It is compiled into bytecode, which is then interpreted by a JVM. The JVM can go and do just-in-time compilation to the native machine language, but doesn't have to do it.

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

More to the point: I think interactivity is the main practical difference. Since everything is interpreted, you can take a small excerpt of code, parse and run it against the current state of the environment. Thus, if you had already executed code that initialized a variable, you would have access to that variable, etc. It really lends itself way to things like the functional style.

更重要的是:我认为交互性是主要的实际区别。由于所有内容都被解释,您可以提取一小段代码,针对当前环境状态解析并运行它。因此,如果您已经执行了初始化变量的代码,您将可以访问该变量等。它确实适用于诸如函数式风格之类的事情。

Interpretation, however, costs a lot, especially when you have a large system with a lot of references and context. By definition, it is wasteful because identical code may have to be interpreted and optimized twice (although most runtimes have some caching and optimizations for that). Still, you pay a runtime cost and often need a runtime environment. You are also less likely to see complex interprocedural optimizations because at present their performance is not sufficiently interactive.

然而,解释的成本很高,尤其是当您拥有一个包含大量参考资料和上下文的大型系统时。根据定义,这是一种浪费,因为相同的代码可能必须被解释和优化两次(尽管大多数运行时都为此进行了一些缓存和优化)。尽管如此,您仍需支付运行时成本,并且通常需要一个运行时环境。您也不太可能看到复杂的过程间优化,因为目前它们的性能不够交互。

Therefore, for large systems that are not going to change much, and for certain languages, it makes more sense to precompile and prelink everything, do all the optimizations that you can do. This ends up with a very lean runtime that is already optimized for the target machine.

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

As for generating executbles, that has little to do with it, IMHO. You can often create an executable from a compiled language. But you can also create an executable from an interpreted language, except that the interpreter and runtime is already packaged in the exectuable and hidden from you. This means that you generally still pay the runtime costs (although I am sure that for some language there are ways to translate everything to a tree executable).

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

I disagree that all languages could be made interactive. Certain languages, like C, are so tied to the machine and the entire link structure that I'm not sure you can build a meaningful fully-fledged interactive version

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

回答by Steven Mohr

It's rather difficult to give a practical answer because the difference is about the language definition itself. It's possible to build an interpreter for every compiled language, but it's not possible to build an compiler for every interpreted language. It's very much about the formal definition of a language. So that theoretical informatics stuff noboby likes at university.

给出一个实际的答案是相当困难的,因为区别在于语言定义本身。可以为每种编译语言构建解释器,但不可能为每种解释语言构建编译器。这在很大程度上与语言的正式定义有关。所以理论信息学的东西在大学里没人喜欢。

回答by Carl Smotricz

The extreme and simple cases:

极端和简单的情况:

  • A compiler will produce a binary executable in the target machine's native executable format. This binary file contains all required resources except for system libraries; it's ready to run with no further preparation and processing and it runs like lightning because the code is the native code for the CPU on the target machine.

  • An interpreter will present the user with a prompt in a loop where he can enter statements or code, and upon hitting RUNor the equivalent the interpreter will examine, scan, parse and interpretatively execute each line until the program runs to a stopping point or an error. Because each line is treated on its own and the interpreter doesn't "learn" anything from having seen the line before, the effort of converting human-readable language to machine instructions is incurred every time for every line, so it's dog slow. On the bright side, the user can inspect and otherwise interact with his program in all kinds of ways: Changing variables, changing code, running in trace or debug modes... whatever.

  • 编译器将以目标机器的本机可执行格式生成二进制可执行文件。该二进制文件包含除系统库之外的所有必需资源;它已准备好运行,无需进一步的准备和处理,它运行起来就像闪电一样,因为代码是目标机器上 CPU 的本机代码。

  • 解释器将在循环中向用户显示提示,他可以在其中输入语句或代码,并且在点击RUN或等效时,解释器将检查、扫描、解析并解释性地执行每一行,直到程序运行到停止点或错误. 因为每一行都是单独处理的,解释器不会从之前看过的行中“学习”任何东西,所以每行每次都会产生将人类可读语言转换为机器指令的工作,所以它很慢。从好的方面来说,用户可以以各种方式检查程序并以其他方式与其交互:更改变量、更改代码、在跟踪或调试模式下运行……等等。

With those out of the way, let me explain that life ain't so simple any more. For instance,

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

  • Many interpreters will pre-compile the code they're given so the translation step doesn't have to be repeated again and again.
  • Some compilers compile not to CPU-specific machine instructions but to bytecode, a kind of artificial machine code for a ficticious machine. This makes the compiled program a bit more portable, but requires a bytecode interpreter on every target system.
  • The bytecode interpreters (I'm looking at Java here) recently tend to re-compile the bytecode they get for the CPU of the target section just before execution (called JIT). To save time, this is often only done for code that runs often (hotspots).
  • Some systems that look and act like interpreters (Clojure, for instance) compile any code they get, immediately, but allow interactive access to the program's environment. That's basically the convenience of interpreters with the speed of binary compilation.
  • Some compilers don't really compile, they just pre-digest and compress code. I heard a while back that's how Perl works. So sometimes the compiler is just doing a bit of the work and most of it is still interpretation.
  • 许多解释器会预编译他们给出的代码,因此翻译步骤不必一次又一次地重复。
  • 一些编译器不编译为特定于 CPU 的机器指令,而是编译为字节码,这是一种用于虚构机器的人工机器代码。这使得编译后的程序更具可移植性,但在每个目标系统上都需要一个字节码解释器。
  • 字节码解释器(我在这里看的是 Java)最近倾向于在执行之前重新编译它们为目标部分的 CPU 获得的字节码(称为 JIT)。为了节省时间,这通常只对经常运行的代码(热点)进行。
  • 一些看起来和行为类似于解释器的系统(例如 Clojure)会立即编译它们获得的任何代码,但允许交互式访问程序环境。这基本上是具有二进制编译速度的解释器的便利。
  • 一些编译器并没有真正编译,它们只是预消化和压缩代码。不久前我听说这就是 Perl 的工作方式。所以有时编译器只是做了一些工作,其中大部分仍然是解释。

In the end, these days, interpreting vs. compiling is a trade-off, with time spent (once) compiling often being rewarded by better runtime performance, but an interpretative environment giving more opportunities for interaction. Compiling vs. interpreting is mostly a matter of how the work of "understanding" the program is divided up between different processes, and the line is a bit blurry these days as languages and products try to offer the best of both worlds.

最后,现在,解释与编译是一种权衡,花费(一次)编译的时间通常会得到更好的运行时性能的回报,但解释性环境提供了更多的交互机会。编译与解释主要是关于“理解”程序的工作如何在不同进程之间划分的问题,现在由于语言和产品试图提供两全其美的优势,这条线有点模糊。

回答by Michael Borgwardt

A compiler and an interpreter do the same job: translating a programming language to another pgoramming language, usually closer to the hardware, often direct executable machine code.

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

Traditionally, "compiled" means that this translation happens all in one go, is done by a developer, and the resulting executable is distributed to users. Pure example: C++. Compilation usually takes pretty long and tries to do lots of expensive optmization so that the resulting executable runs faster. End users don't have the tools and knowledge to compile stuff themselves, and the executable often has to run on a variety of hardware, so you can't do many hardware-specific optimizations. During development, the separate compilation step means a longer feedback cycle.

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

Traditionally, "interpreted" means that the translation happens "on the fly", when the user wants to run the program. Pure example: vanilla PHP. A naive interpreter has to parse and translate every piece of code every time it runs, which makes it very slow. It can't do complex, costly optimizations because they'd take longer than the time saved in execution. But it can fully use the capabilities of the hardware it runs on. The lack of a separrate compilation step reduces feedback time during development.

传统上,“解释”意味着翻译在用户想要运行程序时“即时”发生。纯示例:香草 PHP。一个简单的解释器每次运行时都必须解析和翻译每一段代码,这使得它非常慢。它无法进行复杂、昂贵的优化,因为它们需要的时间比节省的执行时间更长。但它可以充分利用其运行的硬件的功能。缺少单独的编译步骤减少了开发过程中的反馈时间。

But nowadays "compiled vs. interpreted" is not a black-or-white issue, there are shades in between. Naive, simple interpreters are pretty much extinct. Many languages use a two-step process where the high-level code is translated to a platform-independant bytecode (which is much faster to interpret). Then you have "just in time compilers" which compile code at most once per program run, sometimes cache results, and even intelligently decide to interpret code that's run rarely, and do powerful optimizations for code that runs a lot. During development, debuggers are capable of switching code inside a running program even for traditionally compiled languages.

但是现在“编译与解释”不是一个非黑即白的问题,中间有阴影。天真、简单的解释器几乎绝迹了。许多语言使用两步过程,其中将高级代码转换为独立于平台的字节码(解释速度要快得多)。然后你有“及时编译器”,它在每次程序运行时最多编译一次代码,有时缓存结果,甚至智能地决定解释很少运行的代码,并对运行频繁的代码进行强大的优化。在开发过程中,即使对于传统编译语言,调试器也能够在正在运行的程序中切换代码。

回答by lunaryorn

A language itself is neither compiled nor interpreted, only a specific implementation of a language is. Java is a perfect example. There is a bytecode-based platform (the JVM), a native compiler (gcj) and an interpeter for a superset of Java (bsh). So what is Java now? Bytecode-compiled, native-compiled or interpreted?

语言本身既不编译也不解释,只有一种语言的特定实现。Java 就是一个完美的例子。有一个基于字节码的平台(JVM)、一个本地编译器(gcj)和一个 Java 超集的互操作器(bsh)。那么Java现在是什么?字节码编译,本地编译还是解释?

Other languages, which are compiled as well as interpreted, are Scala, Haskell or Ocaml. Each of these languages has an interactive interpreter, as well as a compiler to byte-code or native machine code.

其他既可编译又可解释的语言是 Scala、Haskell 或 Ocaml。这些语言中的每一种都有一个交互式解释器,以及一个字节码或本地机器码的编译器。

So generally categorizing languages by "compiled" and "interpreted" doesn't make much sense.

因此,通常通过“编译”和“解释”对语言进行分类并没有多大意义。

回答by NealB

Start thinking in terms of a: blast from the past

开始思考 a:来自过去的爆炸

Once upon a time, long long ago, there lived in the land of computing interpreters and compilers. All kinds of fuss ensued over the merits of one over the other. The general opinion at that timewas something along the lines of:

很久很久以前,在计算解释器和编译器的土地上生活着。各种大惊小怪随之而来的是一个人比另一个人的优点。普遍的观点在当时是沿着线的东西:

  • Interpreter: Fast to develop (edit and run). Slow to execute because each statement had to be interpreted into machine code every time it was executed (think of what this meant for a loop executed thousands of times).
  • Compiler: Slow to develop (edit, compile, link and run. The compile/link steps could take serious time). Fast to execute. The whole program was already in native machine code.
  • 解释器:快速开发(编辑和运行)。执行缓慢,因为每条语句在每次执行时都必须被解释为机器代码(想想这对于执行数千次的循环意味着什么)。
  • 编译器:开发缓慢(编辑、编译、链接和运行。编译/链接步骤可能需要很长时间)。执行速度快。整个程序已经在本地机器代码中了。

A one or two order of magnitude difference in the runtime performance existed between an interpreted program and a compiled program. Other distinguishing points, run-time mutability of the code for example, were also of some interest but the major distinction revolved around the run-time performance issues.

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

Today the landscape has evolved to such an extent that the compiled/interpreted distinction is pretty much irrelevant. Many compiled languages call upon run-time services that are not completely machine code based. Also, most interpreted languages are "compiled" into byte-code before execution. Byte-code interpreters can be very efficient and rival some compiler generated code from an execution speed point of view.

今天,景观已经发展到如此程度,以至于编译/解释的区别几乎无关紧要。许多编译语言调用不完全基于机器代码的运行时服务。此外,大多数解释型语言在执行前都被“编译”成字节码。字节码解释器非常高效,从执行速度的角度来看,它可以与一些编译器生成的代码相媲美。

The classic difference is that compilers generated native machine code, interpreters read source code and generated machine code on the fly using some sort of run-time system. Today there are very few classic interpreters left - almost all of them compile into byte-code (or some other semi-compiled state) which then runs on a virtual "machine".

经典的区别在于编译器生成本地机器代码,解释器使用某种运行时系统即时读取源代码和生成机器代码。今天只剩下很少的经典解释器了——几乎所有的解释器都编译成字节码(或其他一些半编译状态),然后在虚拟“机器”上运行。

回答by Niko Bellic

The biggest advantage of interpreted source code over compiled source code is PORTABILITY.

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

If your source code is compiled, you need to compile a different executable for each type of processor and/or platform that you want your program to run on (e.g. one for Windows x86, one for Windows x64, one for Linux x64, and so on). Furthermore, unless your code is completely standards compliant and does not use any platform-specific functions/libraries, you will actually need to write and maintain multiple code bases!

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

If your source code is interpreted, you only need to write it once and it can be interpreted and executed by an appropriate interpreter on any platform! It's portable! Note that an interpreter itself is an executable program that iswritten and compiled for a specific platform.

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

An advantage of compiled code is that it hides the source codefrom the end user (which might be intellectual property) because instead of deploying the original human-readable source code, you deploy an obscure binary executable file.

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

回答by Bhavin Shah

From http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-programming-languages

来自http://www.quora.com/What-is-the-difference-between-compiled-and-interpreted-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.

没有区别,因为“编译型编程语言”和“解释型编程语言”不是有意义的概念。任何编程语言,我的意思是任何,都可以被解释或编译。因此,解释和编译是实现技术,而不是语言的属性。

解释是一种技术,通过该技术,另一个程序(解释器)代表被解释的程序执行操作以运行它。如果你能想象阅读一个程序并按照它所说的一步一步地做,比如在一张草稿纸上说,那也正是解释器所做的。解释程序的一个常见原因是解释器相对容易编写。另一个原因是解释器可以监视程序在运行时尝试做什么,以强制执行策略,例如,为了安全。

编译是一种将用一种语言(“源语言”)编写的程序翻译成另一种语言(“对象语言”)的程序的技术,这有望与原始程序具有相同的含义。在进行翻译时,编译器通常也会尝试以使得目标程序更快的方式转换程序(而不改变其含义!)。编译程序的一个常见原因是,有一些很好的方法可以快速运行对象语言中的程序,而无需在此过程中解释源语言的开销。

根据以上定义,您可能已经猜到,这两种实现技术并不是相互排斥的,甚至可能是互补的。传统上,编译器的对象语言是机器代码或类似的东西,它指的是特定计算机 CPU 能够理解的任意数量的编程语言。然后机器代码将“在金属上”运行(尽管人们可能会发现,如果仔细观察,“金属”的工作方式很像解释器)。然而,今天,使用编译器生成旨在解释的目标代码是很常见的——例如,Java 过去(有时仍然如此)工作的方式。有一些编译器可以将其他语言翻译成 JavaScript,然后通常在 Web 浏览器中运行,它可能会解释 JavaScript,或将其编译为虚拟机或本机代码。我们还有机器代码的解释器,可用于在另一种硬件上模拟一种硬件。或者,人们可能会使用编译器生成目标代码,然后将其作为另一个编译器的源代码,后者甚至可能会在内存中及时编译代码以供其运行,反过来。. . 你明白了。有很多方法可以组合这些概念。

回答by Ahmed Shaban Helwa

The Python Book ? 2015 Imagine Publishing Ltd, simply distunguishes the difference by the following hint mentioned in page 10 as:

Python 书?2015 Imagine Publishing Ltd,通过第 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.

Python 等解释型语言是将源代码转换为机器代码,然后在每次程序运行时执行的语言。这与 C 等编译语言不同,在 C 语言中,源代码只转换为机器代码一次——每次程序运行时都会执行生成的机器代码。