当我们说一种语言是动态类型和静态类型时,这意味着什么?
当前回答
编译vs.解释
“当源代码被翻译时”
源代码:原始代码(通常由人输入计算机) 翻译:将源代码转换为计算机可以阅读的内容(即机器代码) 运行时间:程序执行命令的时间(编译后,如果编译) 编译语言:在运行时之前翻译的代码 解释语言:在执行过程中动态翻译的代码
打字
当类型被检查时
5 + '3'是强类型语言(如Go和Python)中类型错误的一个例子,因为它们不允许“类型强制”——>值在某些上下文中改变类型的能力,例如合并两种类型。弱类型语言,如JavaScript,不会抛出类型错误(结果为'53')。
静态:运行前检查的类型 动态:在执行期间动态检查类型
“静态和编译”和“动态和解释”的定义非常相似……但是记住,当类型被检查时。“当源代码被翻译时”。
无论语言是编译的还是解释的,你都会得到相同的类型错误!你需要从概念上区分这些术语。
Python示例
动态的,解释
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
因为Python是解释性的和动态类型的,所以它只翻译和类型检查它所执行的代码。else块永远不会执行,所以5 + '3'甚至永远不会被查看!
如果它是静态类型的呢?
甚至在代码运行之前就会抛出类型错误。即使它是解释的,它仍然在运行时之前执行类型检查。
如果它是编译的呢?
else块将在运行时之前被转换/查看,但因为它是动态类型的,所以不会抛出错误!动态类型语言直到执行才检查类型,而这一行永远不会执行。
去的例子
静态的,编译
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
动态类型更灵活,这一点受到一些人的赞赏。它通常允许变量更改类型,这可能导致意外错误。
其他回答
不幸的是,术语“动态类型”具有误导性。所有语言都是静态类型的,类型是表达式的属性(而不是一些人认为的值的属性)。然而,有些语言只有一种类型。这些被称为单一类型语言。这种语言的一个例子是无类型lambda演算。
在无类型lambda演算中,所有的项都是lambda项,对一个项执行的唯一操作是将它应用到另一个项。因此,所有的操作总是导致无限递归或lambda项,但永远不会发出错误信号。
However, were we to augment the untyped lambda calculus with primitive numbers and arithmetic operations, then we could perform nonsensical operations, such adding two lambda terms together: (λx.x) + (λy.y). One could argue that the only sane thing to do is to signal an error when this happens, but to be able to do this, each value has to be tagged with an indicator that indicates whether the term is a lambda term or a number. The addition operator will then check that indeed both arguments are tagged as numbers, and if they aren't, signal an error. Note that these tags are not types, because types are properties of programs, not of values produced by those programs.
这样做的单一类型语言称为动态类型语言。
JavaScript、Python和Ruby等语言都是单一类型的。同样,JavaScript中的typeof操作符和Python中的type函数的名称具有误导性;它们返回与操作数相关的标记,而不是操作数的类型。类似地,c++中的dynamic_cast和Java中的instanceof不做类型检查。
静态类型语言
如果一个变量的类型在编译时已知,那么该语言就是静态类型的。对于某些语言,这意味着作为程序员的你必须指定每个变量的类型;其他语言(例如:Java, C, c++)提供了某种形式的类型推断,类型系统推断变量类型的能力(例如:OCaml, Haskell, Scala, Kotlin)。
这样做的主要优点是编译器可以完成所有类型的检查,因此在非常早期的阶段就可以捕捉到许多微不足道的错误。
例如:C, c++, Java, Rust, Go, Scala
动态类型语言
如果一种语言的类型与运行时值相关联,而不是命名变量/字段等,则该语言是动态类型的。这意味着作为程序员,您可以编写得更快一些,因为您不必每次都指定类型(除非使用带有类型推断的静态类型语言)。
例如:Perl, Ruby, Python, PHP, JavaScript, Erlang
大多数脚本语言都有这个特性,因为没有编译器来进行静态类型检查,但您可能会发现自己在搜索由于解释器错误解释变量类型而导致的错误。幸运的是,脚本往往很小,所以bug没有那么多藏身之处。
大多数动态类型语言允许您提供类型信息,但不要求提供类型信息。目前正在开发的一种语言Rascal采用了一种混合方法,允许函数内的动态类型,但对函数签名强制执行静态类型。
静态类型语言(如c++、Java)和动态类型语言(如Python)的区别仅仅在于变量类型的执行。 静态类型语言对变量有静态数据类型,这里在编译期间检查数据类型,因此调试要简单得多……而动态类型语言则不这样做,它会检查执行程序的数据类型,因此调试有点困难。
此外,它们有一个非常小的区别,可以与强类型和弱类型语言相关联。强类型语言不允许将一种类型用作另一种类型。C和c++…而弱类型语言允许例如python
静态类型语言(编译器解析方法调用和编译引用):
通常表现更好 更快的编译错误反馈 更好的IDE支持 不适合使用未定义的数据格式 当没有定义模型时,很难开始开发 更长的编译时间 在很多情况下需要编写更多的代码
动态类型语言(在运行程序中做出的决定):
较低的性能 更快的发展 有些bug可能只在稍后的运行时才会被检测到 适用于未定义的数据格式(元编程)
静态类型:在编译时执行的类型检查。
静态类型语言的真正含义是:
必须指定变量的类型 变量只能引用特定类型的对象* 值的类型检查将在编译时执行,任何类型检查都将在此时报告 将在编译时分配内存来存储该特定类型的值
静态类型语言的例子有C、c++、Java。
动态类型:在运行时执行的类型检查。
动态类型语言的真正含义是:
不需要指定变量的类型 同一个变量可以引用不同类型的对象
Python、Ruby都是动态类型语言的例子。
*一些对象可以通过类型转换分配给不同类型的变量(在C和c++等语言中非常常见的做法)