静态类型与动态类型以及强类型与弱类型有什么区别?
静态类型与动态类型以及强类型与弱类型有什么区别?
静态/动态类型 是关于 类型信息何时获取的(是在编译时还是在运行时获取)。
强类型/弱类型 是关于 类型严格程度如何 区分的(例如,语言是否尝试将字符串隐式转换为数字)。
请参阅维基页面以获取更详细的信息。
"12" + "34"
将等于"46"
,但"12" + "34Q"
将等于"1234Q"
[幸运的是,如果想要连接字符串,可以写成"12"&"34"
]。有趣的是,存储数字的变量将其存储为双精度浮点数,并且对这些变量进行数学计算时使用浮点值而不进行字符串操作,但是没有办法询问变量是字符串还是数字。 - supercatObj.magic
的函数,其运行时效果只是返回其参数,但在编译时它将任何类型的值转换为另一种类型。我最喜欢的例子是Modula-3,其设计者称其类型转换结构为LOOPHOLE
。简单来说,静态类型语言的类型是静态的,这意味着一旦将变量设置为某种类型,就无法更改。这是因为类型与变量相关联,而不是与其引用的值相关联。
例如,在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
另一方面,语言中的强/弱类型与隐式类型转换有关(部分摘自@Dario的回答):
例如,在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语言,其中内存地址处的数据可以通过转换被视为不同的数据类型。
在强类型语言中,对象的类型不会改变-整数始终是整数,试图将其用作字符串将导致错误。Java和Python都是强类型语言。
动态类型和静态类型的区别在于何时执行类型检查。在静态类型语言中,每个变量和参数的类型必须在源代码中声明,并在编译时执行强制检查。在动态类型语言中,类型仅在运行时使用时才进行检查。因此,Java是静态类型的,而Python是动态类型的。
但有时边界可能有些模糊。例如,尽管Java是静态类型的,但每次使用反射或强制转换(例如在使用对象容器时)时,都会将类型检查推迟到运行时。
同样,大多数强类型语言仍会自动转换整数和浮点数之间的值(在某些语言中还支持任意精度的BigInts)。
f
接受参数x
(fun f(x)
) [所以没有声明类型],函数体是x+1
。没有声明类型,编译器会推断出x
必须是一个整数。
- fun f x = x + 1;
val f = fn : int -> int
- Filip Bartuzi5 + 'c' // 正确
。 - mehmet这段内容摘自Scott的《编程语言实践》第三版第291页,内容如下:
简单来说,静态/动态类型是指类型检查发生的时间:静态类型是在编译时进行检查,而动态语言是在运行时进行检查。 同样,强/弱类型指的是语言在执行其类型系统时的严格程度。类型检查是确保程序遵守语言类型兼容性规则的过程。违反规则被称为类型冲突。如果一种语言禁止在不支持该操作的任何对象上应用任何操作,并且可以强制执行语言实现,则称其为强类型。如果它是强类型的且可以在编译时进行类型检查,则称之为静态类型。从严格意义上讲,很少有语言是静态类型的。实际上,该术语通常适用于大多数类型检查可以在编译时完成的语言,并且其余部分可以在运行时完成。
几个例子:Ada是强类型语言,大多数情况下是静态类型的(某些类型约束必须在运行时检查)。Pascal实现也可以在编译时执行大部分类型检查,尽管该语言并不完全是强类型的:未标记的变异记录(将在7.3.4节中讨论)是其唯一的漏洞。C89比其前身方言更加强类型,但仍然比Pascal强度要低得多。它的漏洞包括联合体、具有可变数量的子程序。
动态(运行时)类型检查是一种迟绑定形式,并且倾向于出现在将其他问题推迟到运行时的语言中。 Lisp和Smalltalk是动态(尽管强大)类型的。 大多数脚本语言也是动态类型; 有些(例如Python和Ruby)是强类型的。 具有动态作用域的语言通常是动态类型(或根本不需要类型):如果编译器无法确定名称引用的对象,则通常也无法确定对象的类型。
因此,在简单的术语中,静态/动态类型是指类型检查发生的时间:静态类型在编译时进行检查,动态语言在运行时进行检查。 同样,强/弱类型是指语言在执行其类型系统时的严格程度。
我试图将Scott的描述转化为一个漂亮的图表,如下所示:
类型检查在编译时完成
在源代码中,在变量声明时,必须明确指定该变量的数据类型。因为如果在源代码中指定了数据类型,则在编译时将该源代码转换为机器代码并进行类型检查
这里数据类型与变量相关联,如 int count
。而且这种关联是静态或固定的
如果我们尝试通过将其他数据类型的值(int count = “Hello”
)赋给已声明的变量(int count
)来更改已声明变量的数据类型,则会出错
如果我们尝试通过重新声明已声明的变量(int count
)使用其他数据类型(boolean count
),那么我们也会得到错误
int count; /* count is int type, association between data type
and variable is static or fixed */
count = 10; // no error
count = 'Hello'; // error
boolean count; // error
由于类型检查和类型错误检测在编译时完成,因此在运行时不需要进一步的类型检查。因此程序变得更加优化,执行速度更快。
如果我们想要更严格的代码,则选择这种类型的语言是更好的选择。
例如:Java、C、C++、Go、Swift等。
类型检查在运行时完成
在源代码中,在变量声明时,不需要显式指定该变量的数据类型。因为在运行时进行类型检查时,语言系统会从分配给该变量的值的数据类型确定变量类型
这里数据类型与分配给变量的值相关联,例如,var foo = 10
,10是一个数字,所以现在foo是数字数据类型。但这种关联是动态或灵活的
我们可以通过将其他数据类型的值(foo = "Hi"
)分配到已经声明的变量(var foo = 10
)中来轻松更改数据类型,没有错误
我们可以通过使用其他数据类型的值(var foo = true
)重新声明已经声明的变量(var foo = 10
)来轻松更改数据类型,没有错误
var foo; // without assigned value, variable holds undefined data type
var foo = 10; // foo is Number type now, association between data
// type and value is dynamic / flexible
foo = 'Hi'; // foo is String type now, no error
var foo = true; // foo is Boolean type now, no error
由于类型检查和类型错误检测是在运行时进行的,所以程序变得不够优化,导致执行速度变慢。虽然如果它们实现了JIT编译器,这种类型的语言的执行可能会更快。
如果我们想轻松编写和执行代码,那么这种类型的语言是更好的选择,但在这里我们可能会遇到运行时错误。
例如:Python、JavaScript、PHP、Ruby等。
数据类型相关的规则和限制严格遵守
从一个数据类型转换为另一个数据类型必须显式地完成,不能进行隐式类型转换
# in python, "5" cannot automatically get converted to 5
pybar = "5"
print(10 + pybar) # error, no `+` operation between `int` and `str`
类型检查可以在编译时或运行时完成。这意味着强类型语言可以是静态类型或动态类型
例如:Python、Java、Ruby、C#等。
数据类型相关的规则和限制被宽松地维护。
从一个数据类型到另一个数据类型的转换可能会隐式发生。
如果我们在两个不匹配的数据类型之间执行某些操作,则此类语言可能不会抛出错误。相反,弱类型语言将应用其自己的规则进行隐式类型转换,并返回一些结果。
jsbar = "5";
alert(10 + jsbar); /* "105", no error as javascript implicitly coerces Number 10
to String "10", so that it can be concatenated with other operand jsbar i.e. "5" */
类型检查可以在编译时或运行时完成。这意味着弱类型语言可以是静态类型或动态类型。
例如:JavaScript、C、C++、PHP等。