-
23-09-2019 - |
题
我看到这些术语在编程中随处可见,并且我对它们的含义有一个模糊的概念。搜索结果显示,实际上堆栈溢出中已经有人问过这样的问题。据我所知,语言中的静态/动态类型与强/弱类型略有不同,但我不明白这种差异是什么。不同的来源似乎使用不同的含义,甚至可以互换使用这些术语。我找不到地方谈论这两者并实际上阐明了差异。如果有人能在这里为我和世界其他人清楚地阐明这一点,那就太好了。
解决方案
静态/动态打字 是关于 什么时候 获取类型信息(在编译时或运行时)
强/弱类型 是关于 多么严格 类型是区分的(例如该语言是否尝试进行从字符串到数字的隐式转换)。
请参阅 维基页面 了解更多详细信息。
其他提示
您已经发现在业余爱好者用来谈论编程语言的术语情有独钟。 不要使用“强”和“弱”打字,因为他们没有做一个普遍认同的技术含义。与此相反,的静态类型表示该节目是的被执行之前,然后开始之前的节目可能被拒绝检查。的动态类型表示该类型的的 值被检查期间执行,然后类型化不良操作可能导致程序到停止或以其他方式的在运行时强>发出错误信号。对于静态类型的主要原因是为了排除可能有这样的“动态类型的错误”的节目。
<强>强类型强>通常是指有否漏洞强>在类型系统,而<强>弱类型表示的类型的系统可被颠覆(无效任何保证)。该术语经常被误用来平均静态和动态类型。 要看到其中的差别,认为C的:语言是类型检查在编译时(静态类型),但也有很多漏洞;你几乎可以施放任何类型的值到另一种类型的尺寸相同的---尤其是,你可以自由地施展指针类型。帕斯卡尔是意欲是强类型,但著名的有一个不可预见的漏洞语言:没有标签的变体记录
强类型语言的实现经常获取漏洞随着时间的推移,通常使得在运行时系统的一部分所用的高级语言来实现。例如,目的CAML有一个称为Obj.magic
其具有简单地返回它的参数运行时作用的功能,但在编译时将其转换的任何类型的任何其他类型中的一个的值。我喜欢的例子是MODULA-3,其设计者称他们的类型铸造构建LOOPHOLE
de。
说了这么多,你不能使用词语的完全相同的方式“强”和“弱”任何两个人算。所以避免它们。
简单地说是这样:在静态类型语言的类型的静态的,这意味着一旦你设置一个变量的类型,你不能改变它。这是因为分型与变量,而不是它指的是值相关联。
例如在Java中:
String str = "Hello"; //statically typed as string
str = 5; //would throw an error since java is statically typed
而在一个的动态类型语言强>类型是动态,这意味着你设置为一个类型的变量之后,可以改变它。这是因为分型与值而不是变量相关联。
例如在Python:
str = "Hello" # it is a string
str = 5 # now it is an integer; perfectly OK
在另一方面,在强/弱类型强>在一个语言有关隐式类型转换(部分取自@达里奥回答):
例如在Python:
str = 5 + "hello"
# would throw an error since it does not want to cast one type to the other implicitly.
而在PHP:
$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0
// PHP is weakly typed, thus is a very forgiving language.
静态类型允许在编译时检查类型正确性。静态类型语言通常编译,动态类型语言的解释。因此,动态地类型化的语言可以在运行时检查打字。
弱类型的装置,一个对象的类型可以根据上下文而改变。例如,在弱类型语言字符串“123”,如果你添加另一个号码给它可以被视为数字123。与弱类型语言的例子是bash中,AWK和PHP。
另一种弱类型语言的是C,其中在存储器地址中的数据可以被处理为不同类型的通过铸造。
在强类型语言的对象的类型并不改变 - 一个int总是一个int,并试图使用它作为一个串将导致一个错误。 Java和Python的是强类型。
动态和静态类型之间的差别是当类型规则强制执行。在静态类型语言中的每个变量和参数的类型必须在源中声明,并且在编译时执行。在动态类型语言,当他们在运行时使用只检查类型。所以Java是静态类型和Python是动态类型。
然而边界有时可能有点模糊。例如虽然Java是静态类型,每次使用反射或流延(例如,使用对象的容器时)它们您推迟类型检查到的运行时间。
类似地最强类型语言仍然会自动整数和浮点数之间的转换(以及在一些语言abitrary精度BigInts)。
今天,研究这个课题我碰到这篇大文章的 http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html 它清理了很多东西对我来说而且我认为这可能会增加一些上面的大的答案。
强类型:
可能是最常见的方式类型的系统被分类为“强” 或“弱”。这是不幸的,因为这些词有几乎没有 在所有的意义。这是,在有限程度上,可以比较两个 具有非常相似类型的系统,并且指定一个作为具有语言 这两个系统的强大。除此之外,话没什么意思 在所有。
静态和动态类型
这是非常接近的类型系统的唯一共同分类 具有实际意义。作为事实上,它的意义在于 经常低估[...]动态和静态类型系统 两个完全不同的东西,他的目标发生部分 重叠。
一个静态类型系统是一种机制,通过该编译器检查 源代码和受让人标签(称为“类型”),以的片 语法,然后用它们来推断一些关于该程序的 行为。动态型系统是一种机制,通过该编译器 生成代码,以排序的数据(的轨道巧合的是,也 叫程序使用它的“类型”)。使用同一个词的 在每一个这两个系统的“类型”是的,当然,不是真的完全 巧合;然而,这是最好理解为具有某种弱 历史意义。从试图找到一个很大的混乱结果 世界观中,“类型”的真正含义在这两个同样的事情 系统。它没有。
显式/隐类型:
当使用这些术语,它们是指在何种程度上一个 编译器将推理的静态类型程序的部分。所有 编程语言有某种形式的推理类型。一些 有比别人更多。 ML和Haskell有隐含的类型,在没有 (或极少,这取决于所使用的语言和扩展)类型 需要声明。 Java和Ada的有非常明确的类型,以及 一个是不断声明类型的东西。所有上面有 (相对,相对于C和C ++,例如)强静电型 系统
来自斯科特的 编程语言语用学, ,第 3 版第 291 页,我们有
类型检查是确保程序遵守语言类型兼容性规则的过程。违反规则被称为类型冲突。据说有一种语言是 强类型 如果它禁止使用语言实施的方式,则将任何操作应用于任何不打算支持该操作的对象。据说有一种语言是 静态类型 如果强烈键入并且可以在编译时进行类型检查。从该术语中最严格的意义上,很少有语言在静态上键入。实际上,该末日通常应用于可以在编译时执行大多数类型检查的语言,其余的可以在运行时执行。
举几个例子:ADA是强烈键入的,并且在大多数情况下静态键入(必须在运行时检查某些类型的约束)。尽管语言不是很强烈键入,但Pascal实施也可以在编译时进行大部分类型检查:未标记的变体记录(在第7.3.4节中进行讨论)是其唯一的漏洞。C89比其前身方言更强大,但与帕斯卡尔的键入相比仍然要少得多。它的漏洞包括工会,参数数量可变数量以及指针和数组的互操作性(请在第7.7.1节中进行讨论)。C的实现很少在运行时检查任何内容。
动态(运行时)类型检查是一种较晚绑定的一种形式,并且倾向于在将其他问题推迟到运行时的语言中找到。Lisp 和 Smalltalk 是动态(尽管是强)类型的。大多数脚本语言也被动态键入;有些(例如,Python和Ruby)强烈键入。具有动态范围的语言通常是动态键入的(或根本不键入):如果编译器无法识别名称所指的对象,则通常无法确定对象的类型。
所以简单来说,静态/动态类型指的是类型检查发生的时间:静态类型的编译时间和动态语言的运行时间。同样,强/弱类型指的是一种语言在强制执行其类型系统方面的积极程度。
我试图将斯科特的描述翻译成一个漂亮的图表,我将其发布在下面。
我认为其他同事做得很好,尤其是。解释静态类型和动态类型之间的区别。但是,就强大和弱打字而言,应该说有不同的理解/观点。
这里有两个例子:
有人说 Haskell 是强类型的,因为你不允许 任何 类型转换。
其他(例如Dario 的观点)说,允许有意从字符串隐式转换为数字的语言是弱类型的,但甚至其他人也称这只是鸭子类型。
这两种说法都强调的不是类型系统的相反极端,而是完全不同的方面。于是我就加入了先生的行列。Ramsey 认为不要使用术语“强”和“弱”来区分类型系统。
静态类型与动态类型语言
- 静态类型语言是在编译时进行类型检查的语言,因此这也意味着在静态类型语言中,每个变量都有一个类型,并且在整个过程中不会改变。 现在,相比之下, 动态类型语言是在运行时进行类型检查的语言,并且在编译时没有类型检查,因此这也意味着在动态类型语言中可能存在也可能不存在与变量关联的类型, ,如果关联了一个类型,那么它可能是一个通用类型,比如 JS 中的“var”,它适用于字符串和数字。
- “动态类型检查语言的实现通常将每个运行时对象与包含其类型信息的类型标记(即对类型的引用)相关联。此运行时类型信息 (RTTI) 还可用于实现动态调度、后期绑定、向下转换、反射和类似功能。”
- 即使语言是静态类型的,它仍然可以具有一些动态类型的功能,这基本上意味着在运行时也进行某种类型检查。这在类型转换时很有用。
- “许多有用且常见的编程语言功能无法静态检查,例如向下转换。因此,许多语言都具有静态和动态类型检查;静态类型检查器验证它能做什么,动态检查验证其余的。”
- “有些语言允许编写非类型安全的代码。例如,在 C 中,程序员可以在具有相同大小的任意两种类型之间自由转换值。”
- “静态”类型语言的优点是:
- 由于大多数类型检查是在编译时完成的,因此解释器或运行时可以全速运行,而不必担心类型。
- 它会导致较少数量的运行时异常或与类型相关的错误,因为大多数类型检查是在编译时完成的。
- “动态”类型语言的优点是:
- 它们可以帮助实现极快的原型设计,因为开发人员不需要了解类型系统,因此开发人员可以松散地创建变量并运行它,这会导致非常快速的原型设计。
- 静态和动态类型语言列表:
- 静态地:
- 爪哇
- C(C 是一种静态类型语言,但与 Java 相比,“强”类型较少,因为它允许更多隐式转换)
- C++
- C#
- 动态地:
- PERL
- PHP
- Python
- JavaScript
- 红宝石
- 静态地:
- 类型检查是一项重要的安全功能。 假设没有类型检查,并且一个方法接受“BankAccount”类型的对象,该对象有一个名为“creditAccount(BankAccountDetails)”的方法,现在在运行时如果没有类型检查,那么我可以传递我自己的对象类具有相同的方法“creditAccount(BankAccountDetails)”并且它将被执行,考虑到我们正在谈论面向对象语言,因为OOP支持“多态性”,而这里我们讨论的只是“多态性”。因此,基本上,一种没有强大类型检查的面向对象语言(这基本上意味着它支持“多态性”)可能会导致安全问题。
强类型语言与弱类型语言
- 强类型语言是那些如果存在精度损失则不允许隐式转换的语言。例如,在 Java 中,您可以将“int 转换为 long”,因为不会损失精度,但您不能“隐式”将“long 转换为 int”,因为会损失精度。相反,在弱类型语言中,即使存在精度损失,也允许隐式转换。
- 我认为动态类型语言也可以是强类型语言,如果“在运行时”它不允许进行会导致精度损失的隐式转换。
很好的进一步阅读
静态类型语言通常需要您声明变量的类型,然后检查在编译时减少错误。在“静态类型”字“静态”指的是“静态代码分析”,这是为了执行它之前检查代码的处理。虽然这是可能的静态类型语言来推断从表达式或实际参数的右手侧的变量的类型,在实践中大多数静态类型语言需要变量类型进行明确声明。
动态类型语言通常不要求变量声明有类型的,他们推断依据,因为每个赋值语句或实际参数的右侧评估一个函数调用的结果计算的那种类型的变量类型。由于变量可以被赋予在其生命周期的多个任务,它的类型可以随时间而改变,这就是为什么它被称为“动态类型”。此外,运行环境需要跟踪当前的类型为每个变量的,所以类型绑定到值而不是与变量声明。这可以被认为是一种运行时类型信息(RTTI)系统。
静态和动态类型语言的元素可以组合。例如,C#同时支持静态和动态类型的变量,以及面向对象的语言通常支持下铸型层次。静态类型语言通常通过使用铸造,反射和动态调用提供各种方法来旁路类型检查,例如
强与弱类型指的语言多少试图防止错误由于使用可变,好像它是一个类型时,它实际上是在另一种类型的连续体。例如C和Java是静态类型语言,但Java使用更强大的类型检查比做C.下面的C代码很高兴地编译和运行,并把一个随机值到变量b在运行时,最有可能导致错误:
char *a = "123";
int b = (int)a;
等效Java代码将产生一个编译错误,这通常是优选的:
String a = "123"
int b = (int)a;