静态类型语言和动态类型语言有什么区别?

时间:2009-10-04 22:36:11

标签: programming-languages static-typing dynamic-typing

我听到很多新的编程语言是动态类型的,但当我们说某种语言是动态类型而非静态类型时,它实际意味着什么呢?

17 个答案:

答案 0 :(得分:738)

静态类型语言

如果在编译时已知变量的类型,则静态输入语言。对于某些语言,这意味着您作为程序员必须指定每个变量的类型(例如:Java,C,C ++);其他语言提供某种形式的类型推断,类型系统推断变量类型的能力(例如:OCaml,Haskell,Scala,Kotlin)

这里的主要优点是所有类型的检查都可以由编译器完成,因此在很早的阶段就会发现很多琐碎的错误。

示例:C,C ++,Java,Rust,Go,Scala

动态类型语言

如果类型与运行时值相关联,而不是命名变量/字段/等,则动态类型化语言。这意味着您作为程序员可以更快地编写,因为您不必每次都指定类型(除非使用带有类型推断的静态类型语言)。

示例:Perl,Ruby,Python,PHP,JavaScript

大多数脚本语言都有此功能,因为无论如何都没有编译器可以执行静态类型检查,但您可能会发现自己正在搜索由于解释器误解变量类型而导致的错误。幸运的是,脚本往往很小,所以错误没有那么多地方可以隐藏。

大多数动态类型语言都允许您提供类型信息,但不需要它。目前正在开发的一种语言Rascal采用混合方法,允许在函数内动态键入,但强制执行函数签名的静态类型。

答案 1 :(得分:325)

静态类型编程语言在编译时进行类型检查(即验证和强制执行类型约束的过程),而不是运行时

动态类型编程语言在运行时进行类型检查,而不是编译时

答案 2 :(得分:275)

以下是对比Python(动态类型)和Go(静态类型)如何处理类型错误的示例:

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

Python在运行时进行类型检查,因此:

silly(2)

运行完全正常,并产生预期的输出Hi。只有在遇到有问题的行时才会出错:

silly(-1)

可生产

TypeError: unsupported operand type(s) for +: 'int' and 'str'

因为实际执行了相关的行。

另一方面,在编译时进行类型检查:

package main

import ("fmt"
)

func silly(a int) {
    if (a > 0) {
        fmt.Println("Hi")
    } else {
        fmt.Println("3" + 5)
    }
}

func main() {
    silly(2)
}

以上将无法编译,并出现以下错误:

invalid operation: "3" + 5 (mismatched types string and int)

答案 3 :(得分:139)

简单地说就是这样:在静态类型语言变量'类型是静态,这意味着一旦将变量设置为类型,就无法更改它。这是因为键入与变量而不是它所引用的值相关联。

例如在Java中:

food_list = [f.id for f in Food.objects.filter(food_id__in=cart['food'])]

另一方面:在动态类型语言变量'类型是动态,这意味着在将变量设置为类型后,您可以更改它。这是因为打字与它所假定的值相关联,而不是与变量本身相关联。

例如在Python中:

String str = "Hello";  //variable str statically typed as string
str = 5;               //would throw an error since str is supposed to be a string only

因此,最好将动态类型语言中的变量视为只是通用指针来键入值。

总而言之,类型描述(或应该描述)语言中的变量而不是语言本身。它可以更好地用作具有静态类型变量的语言具有动态类型变量的语言恕我直言。

静态类型语言通常是编译语言,因此,编译器检查类型(完美正确吗?因为不允许稍后在运行时更改类型)。

通常会解释动态类型语言,因此在使用它们时会在运行时进行类型检查(如果有)。这当然会带来一些性能成本,并且是动态语言(例如,python,ruby,php)不能像键入的那些(java,c#等)那样扩展的原因之一。从另一个角度来看,静态类型语言具有更多的启动成本:使您通常编写更多代码,更难编写代码。但是后来付出了代价。

好处是双方都在借用另一方的特征。类型化语言包含更多动态特性,例如c#中的泛型和动态库,动态语言包括更多类型检查,例如python中的类型注释,或PHP的HACK变体,它们通常不是语言的核心,可用于需求。

在技术选择方面,双方都没有内在的优势。您是想要更多控制开始还是灵活性,这只是一个偏好问题。只需为工作挑选合适的工具,并确保在考虑开关之前检查相反的可用工具。

答案 4 :(得分:38)

答案 5 :(得分:14)

不幸的是,“动态打字”这个术语具有误导性。所有语言都是静态类型的,类型是表达式的属性(不像某些人认为的那样是值)。但是,某些语言只有一种类型。这些被称为单类型语言。这种语言的一个例子是无类型的lambda演算。

在无类型的lambda演算中,所有术语都是lambda术语,并且可以对术语执行的唯一操作是将其应用于另一个术语。因此,所有操作总是导致无限递归或lambda项,但从不发出错误信号。

然而,如果我们用原始数和算术运算来扩充无类型lambda演算,那么我们可以执行无意义的操作,例如将两个lambda项一起添加:(λx.x) + (λy.y)。有人可能会争辩说,唯一明智的做法就是在发生这种情况时发出错误信号,但为了能够做到这一点,每个值都必须用一个指示符来标记,该指示符指示该术语是lambda术语还是数字。然后,加法运算符将检查两个参数是否都被标记为数字,如果不是,则表示错误。请注意,这些标记是不是类型,因为类型是程序的属性,而不是这些程序生成的值。

执行此操作的单类型语言称为动态类型。

JavaScript,Python和Ruby等语言都是单类型的。同样,JavaScript中的typeof运算符和Python中的type函数具有误导性的名称;它们返回与操作数关联的标记,而不是它们的类型。类似地,C ++中的dynamic_cast和Java中的instanceof 进行类型检查。

答案 6 :(得分:5)

编译与解释

"翻译源代码"

  • 源代码:原始代码(通常由人类输入计算机)
  • 翻译:将源代码转换为计算机可以读取的内容(即机器代码)
  • 运行时:程序执行命令的时间段(编译后,如果已编译)
  • 编译语言:在运行时翻译的代码
  • 口译语言:执行期间即时翻译的代码

输入

"检查类型"

5 + '3'强类型语言(如Go和Python)中类型错误的一个示例,因为它们不允许"类型强制" - >值在某些上下文中更改类型的能力,例如合并两种类型。 弱类型的语言(例如JavaScript)不会抛出类型错误(导致'53')。

  • 静态:在运行时检查的类型
  • 动态:执行期间动态检查的类型

"静态& amp;的定义编译"和"动态&解释"非常相似...但请记住它的类型,检查类型" vs."当源代码被翻译时#34;。

无论语言是编译还是解释,您都会遇到相同类型的错误!您需要在概念上区分这些术语。

Python示例

动态,解释

def silly(a):
    if a > 0:
        print 'Hi'
    else:
        print 5 + '3'

silly(2)

因为Python既被解释又被动态地键入,因此它只对它正在执行的代码进行翻译和类型检查。 else块永远不会执行,所以5 + '3'永远不会被查看!

如果是静态类型怎么办?

在代码运行之前会抛出类型错误。它仍然在运行时执行类型检查,即使它被解释。

如果编译了怎么办?

else块将在运行时被翻译/查看,但由于它是动态输入的,因此不会抛出错误!动态类型语言在执行之前不会检查类型,并且该行永远不会执行。

Go Example

静态,已编译

package main

import ("fmt"
)

func silly(a int) {
  if (a > 0) {
      fmt.Println("Hi")
  } else {
      fmt.Println("3" + 5)
  }
}

func main() {
  silly(2)
}

在运行之前检查类型(静态),并立即捕获类型错误!如果解释了类型,则在运行时仍会检查这些类型,结果相同。如果它是动态的,即使在编译期间查看代码,它也不会抛出任何错误。

效果

如果编译语言的静态类型(动态对比),则它在运行时会有更好的性能;类型知识允许机器代码优化。

静态类型语言在运行时本质上具有更好的性能,因为不需要在执行时动态检查类型(它在运行之前检查)。

类似地,编译语言在运行时更快,因为代码已经被翻译而不是需要"解释" /在运行中翻译它。

请注意,编译和静态类型语言在运行转换和类型检查之前都会有延迟。

更多差异

静态类型提前捕获错误,而不是在执行期间找到它们(对于长程序尤其有用)。它更严格"严格"因为它不会在程序中的任何地方允许类型错误,并且通常会阻止变量更改类型,从而进一步防止意外错误。

num = 2
num = '3' // ERROR

动态打字更灵活,有些人欣赏。它通常允许变量更改类型,这可能导致意外错误。

答案 7 :(得分:5)

静态类型语言在编译时进行类型检查,类型不能更改。 (不要用类型转换注释变得可爱,创建一个新的变量/引用)。

动态类型语言在运行时进行类型检查,并且可以在运行时更改变量的类型。

答案 8 :(得分:4)

甜蜜而简单的定义,但符合需要: 静态类型语言将类型绑定到整个范围的变量(Seg:SCALA) 动态类型语言将类型绑定到变量引用的实际值。

答案 9 :(得分:4)

静态类型语言:每个变量和表达式在编译时都已知。

int a; a在运行时只能取整数类型的值)

示例:C,C ++,Java

动态类型语言:变量可以在运行时接收不同的值,并且它们的类型是在运行时定义的。

var a; a可以在运行时获取任何类型的值)

示例:Ruby,Python。

答案 10 :(得分:3)

  • 在静态类型语言中,变量与在编译时已知的类型相关联,并且该类型在程序执行期间保持不变。同样,只能为变量分配一个值,该值是已知/指定类型的实例。
  • 在动态类型语言中,变量没有类型,执行期间的值可以是任何形状和形式。

答案 11 :(得分:2)

静态类型的语言(例如C ++,Java)和动态类型的语言(例如Python)仅在变量类型执行方面有所不同。    静态类型语言具有用于变量的静态数据类型,此处数据类型在编译过程中进行了检查,因此调试非常简单...而动态类型语言则不会同样,要检查执行程序的数据类型,因此调试有点困难。

此外,它们之间的差异很小,可以与强类型弱类型语言相关。强类型语言不允许您将一种类型用作另一种类型。 C和C ++ ...弱类型语言允许例如python

答案 12 :(得分:1)

静态类型

在运行时检查类型,以便更早发现错误。

示例= c ++

动态键入

在执行期间检查类型。

示例= Python

答案 13 :(得分:0)

动态类型语言有助于快速构建算法概念原型,而无需考虑需要使用哪些变量类型(这是静态类型语言 e中的必需品) 。

答案 14 :(得分:0)

静态类型语言(编译器解析方法调用并编译引用):

  • 通常更好的表现
  • 更快的编译错误反馈
  • 更好的IDE支持
  • 不适合使用未定义的数据格式
  • 在未定义模型时更难以开始开发
  • 更长的编译时间
  • 在许多情况下,需要编写更多代码

动态类型语言(在运行程序中进行的决定):

  • 性能降低
  • 更快的发展
  • 某些错误可能仅在运行时稍后才能检测到
  • 适用于未定义的数据格式(元编程)

答案 15 :(得分:0)

静态类型在编译时执行的类型检查

静态类型语言的实际含义:

  • 必须指定变量的类型
  • 一个变量只能引用特定类型的对象*
  • 将在编译时对值进行类型检查,届时将报告任何类型检查
  • 将在编译时分配内存以存储该特定类型的值

静态类型语言的例子有 C、C++、Java。

动态类型在运行时执行类型检查

动态类型语言的实际含义:

  • 无需指定变量类型
  • 同一个变量可以引用不同类型的对象

Python、Ruby 是动态类型语言的例子。


* 某些对象可以通过类型转换分配给不同类型的变量(在 C 和 C++ 等语言中很常见的做法)

答案 16 :(得分:-13)

静态打字: Java和Scala等语言是静态类型的。

必须先定义和初始化变量,然后才能在代码中使用它们。

代表。 int x; x = 10;

的System.out.println(X);

动态打字:  Perl是一种动态类型语言。

在代码中使用变量之前,无需初始化变量。

Y = 10;在代码的后半部分使用此变量