静态/动态类型和强/弱类型之间的区别是什么?


当前回答

摘自Addison Wesley,《面向对象的分析与应用设计》,第3期,第66页:

The concepts of strong and weak typing and static and dynamic typing are entirely different. Strong and weak typing refers to type consistency, whereas static and dynamic typing refers to the time when names are bound to types. Static typing (also known as static binding or early binding) means that the types of all variables and expressions are fixed at the time of compilation; dynamic typing (also known as late binding) means that the types of all variables and expressions are not known until runtime. A language may be both strongly and statically typed (Ada), strongly typed yet supportive of dynamic typing (C++, Java), or untyped yet supportive of dynamic typing (Smalltalk).

其他回答

在编程中,数据类型是一种分类,它告诉变量将持有什么类型的值,以及可以对这些值进行哪些数学、关系和逻辑操作而不会出错。

在每种编程语言中,为了尽量减少出错的机会,类型检查都是在程序执行之前或执行过程中进行的。根据类型检查的时间,编程语言有两种类型:静态类型语言和动态类型语言。

也取决于是否发生隐式类型转换,编程语言有两种类型:强类型语言和弱类型语言。

静态类型:

Type checking is done at compile time In source code, at the time of variable declaration, data type of that variable must be explicitly specified. Because if data type is specified in source code then at compile time that source code will be converted to machine code and type checking can happen Here data type is associated with variable like, int count. And this association is static or fixed If we try to change data type of an already declared variable (int count) by assigning a value of other data type (int count = "Hello") into it, then we will get error If we try to change data type by redeclaring an already declared variable (int count) using other data type (boolean count) then also we will get error

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等。

动态类型:

Type checking is done at runtime In source code, at the time of variable declaration, no need to explicitly specify data type of that variable. Because during type checking at runtime, the language system determines variable type from data type of the assigned value to that variable Here data type is associated with the value assigned to the variable like, var foo = 10, 10 is a Number so now foo is of Number data type. But this association is dynamic or flexible we can easily change data type of an already declared variable (var foo = 10), by assigning a value of other data type (foo = "Hi") into it, no error we can easily change data type of an already declared variable (var foo = 10), by redeclaring it using value of other data type (var foo = true), no error

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等。

今天在研究这个主题时,我看到了这篇很棒的文章http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html,它为我理清了很多事情,我认为它可能会为上面的一些伟大的答案补充一些东西。

强和弱打字:

可能类型系统最常见的分类方法是“强” 或“弱”。这是不幸的,因为这些话几乎没有 完全没有意义。在有限的范围内,比较两者是可能的 具有非常相似类型系统的语言,并指定其中一个为具有 这两个系统中较强的一个。除此之外,这些话毫无意义 在所有。

静态和动态类型

This is very nearly the only common classification of type systems that has real meaning. As a matter of fact, it's significance is frequently under-estimated [...] Dynamic and static type systems are two completely different things, whose goals happen to partially overlap. A static type system is a mechanism by which a compiler examines source code and assigns labels (called "types") to pieces of the syntax, and then uses them to infer something about the program's behavior. A dynamic type system is a mechanism by which a compiler generates code to keep track of the sort of data (coincidentally, also called its "type") used by the program. The use of the same word "type" in each of these two systems is, of course, not really entirely coincidental; yet it is best understood as having a sort of weak historical significance. Great confusion results from trying to find a world view in which "type" really means the same thing in both systems. It doesn't.

显式或隐式类型:

When these terms are used, they refer to the extent to which a compiler will reason about the static types of parts of a program. All programming languages have some form of reasoning about types. Some have more than others. ML and Haskell have implicit types, in that no (or very few, depending on the language and extensions in use) type declarations are needed. Java and Ada have very explicit types, and one is constantly declaring the types of things. All of the above have (relatively, compared to C and C++, for example) strong static type systems.

Statically typed languages generally require you to declare the types of variables, which is then checked at compile time to reduce errors. The word "static" in "statically typed" refers to "static code analysis", which is the process of examining the code prior to executing it. Although it is possible for a statically typed language to infer the type of the variable from the right hand side of an expression or actual parameters, in practice most statically typed languages require variable types to be explicitly declared.

Dynamically typed languages generally do not require variable declarations to have types, and they infer variable types based on the type calculated as a result of evaluating the right hand side of every assignment statement or the actual parameters to a function call. Since the variable can be given multiple assignments over its lifetime, its type can change over time and this is why it is called "dynamically typed". Also, the runtime environment needs to keep track of the current type for each variable, so the type is bound to the value rather than with the variable declaration. This can be considered a runtime type information (RTTI) system.

静态类型语言和动态类型语言的元素可以组合。例如,c#既支持静态类型变量,也支持动态类型变量,而面向对象语言通常支持类型层次结构的向下转换。静态类型语言通常提供各种绕过类型检查的方法,例如使用强制转换、反射和动态调用。

强类型和弱类型指的是语言在多大程度上试图防止由于使用变量而导致的错误,就好像它是一种类型,而实际上它是另一种类型。例如,C和Java都是静态类型语言,但是Java使用了比C强大得多的类型检查。下面的C代码很容易编译和运行,并会在运行时将一个随机值放入变量b中,很可能会导致错误:

char *a = "123";
int b = (int)a;

等效的Java代码将产生一个编译错误,这通常是可取的:

String a = "123"
int b = (int)a;

静态v/s动态类型语言

Statically typed languages are those in which type checking is done at the compile time, so this also means that in statically typed languages each variable has a type and it doesn’t change over the course. Now, in contrast, dynamically typed languages are those in which type checking is done at runtime, and there is no type checking at compile time, so this also means that in dynamically typed languages there may or may not be a type associated with a variables, and if a type is associated then it could be a generic type like “var” in JS which hold good for both a string and number. “Implementations of dynamically type-checked languages generally associate each runtime object with a type tag (i.e., a reference to a type) containing its type information. This runtime type information (RTTI) can also be used to implement dynamic dispatch, late binding, down casting, reflection, and similar features.” Even if language is statically typed, still it could have some dynamically typed feature, which basically means that some sort of type checking at runtime as well. This is useful in casting of types. “A number of useful and common programming language features cannot be checked statically, such as down casting. Thus, many languages will have both static and dynamic type checking; the static type checker verifies what it can, and dynamic checks verify the rest.” “Some languages allow writing code that is not type-safe. For example, in C, programmers can freely cast a value between any two types that have the same size.” Advantage of “statically” typed languages are that: Since most of the type checking is done at compile time so interpreter or runtime can run at full speed, without worrying about the types. It leads to lesser number of runtime exception or errors related to type, because most of the type checking is done at compile time. Advantage of “dynamically” typed languages are that: They could help in extremely fast prototyping, since developer need not to understand the type system so dev can loosely create variables and run it, and this leads to very fast prototyping. List of statically and dynamically typed languages: Statically: Java C (C is a statically typed language but lesser “strongly” typed as compared to Java because it allows more implicit conversions) C++ C# Dynamically: PERL PHP Python JavaScript Ruby Type checking is an important security feature. Suppose, there is no type checking, and a method accepts an object of type “BankAccount” which has a method called as “creditAccount(BankAccountDetails)”, now at runtime if there is no type checking then I can pass an object of my own class which has same method “creditAccount(BankAccountDetails)” and it will get executed, considering we are talking about object oriented language because OOP supports “polymorphism” and here what we are discussing is nothing but “polymorphism”. So, basically an object oriented language (which basically means it supports “polymorphism”) which doesn’t have strong type checking can lead to security issues.

强v/s弱类型语言

Strongly typed languages are those in which implicit conversions are not allowed if there is loss of precision. For example, in Java, you can cast an “int to long” because there is no loss of precision but you cannot “implicitly” cast a “long to int” because there would be loss of precision. In contrast, in weakly typed languages, implicit conversions are allowed even if there is loss of precision. I think dynamically typed language can also be a strongly typed language if “at runtime” it doesn’t allow implicit conversions in which there is loss of precision.


很好的进一步阅读

Type_system Strong_and_weak_typing 类别:Statically_typed_programming_languages 类别:Dynamically_typed_programming_languages

我认为其他同事做得很好,特别是解释了静态类型和动态类型的区别。但就强类型和弱类型而言,应该说都有 不同的理解/观点。

这里有两个例子:

有人说Haskell是强类型的,因为不允许进行任何类型转换。 其他人(例如Dario的观点)说,允许有意地从字符串隐式转换为数字的语言是弱类型的,但甚至其他人称之为鸭子类型。

这两种说法强调的不是类型系统的两个极端,而是完全不同的方面。因此,我同意Ramsey先生的观点,不要用“强”和“弱”来区分类型系统。