强类型语言和静态类型语言的区别是什么?

另外,两者之间是否存在关联?

289483 次浏览

强烈 typed表示类型之间的转换有限制。

静态 typed意味着该类型不是动态的——一旦创建了变量,就不能更改它的类型。

这一点经常被误解,所以让我澄清一下。

静态/动态类型

静态类型是类型绑定到变量的地方。在编译时检查类型。

动态类型是类型绑定到价值的地方。类型在运行时检查。

以Java为例:

String s = "abcd";

s将永远是String。在它的生命周期中,它可能指向不同的# eyz1(因为s在Java中是一个引用)。它可能有一个null值,但它永远不会指向IntegerList。这就是静态类型。

在PHP中:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

这就是动态类型。

强/弱类型

(编辑提醒!)

强类型是一个没有广泛共识的短语。大多数程序员使用这个术语来表示静态类型以外的其他含义,他们使用它来暗示编译器强制执行一种类型规则。例如,CLU有一个强类型系统,它不允许客户端代码创建抽象类型的值,除非使用类型提供的构造函数。C语言有一个强类型系统,但在某种程度上它可以被“颠覆”,因为程序总是可以将一种指针类型的值强制转换为另一种指针类型的值。例如,在C语言中,你可以取一个由malloc()返回的值,并愉快地将它转换为FILE*,编译器不会试图阻止你,甚至不会警告你正在做任何可疑的事情。

(最初的答案说了一些关于值“在运行时不改变类型”的内容。我认识许多语言设计者和编译器作者,但没有一个人谈论过在运行时改变类型的值,除了一些类型系统的非常高级的研究,在那里这被称为“强更新问题”。)

弱类型意味着编译器不强制执行类型规则,或者可能这种强制很容易被破坏。

这个答案的原始版本将弱输入与隐式转换(有时也称为“隐式提升”)混为一谈。例如,在Java中:

String s = "abc" + 123; // "abc123";

这段代码是隐式提升的一个例子:123在与"abc"连接之前隐式转换为字符串。可以这样说,Java编译器将代码重写为:

String s = "abc" + new Integer(123).toString();

考虑一个经典的PHP“以”开头的问题:

if (strpos('abcdef', 'abc') == false) {
// not found
}

这里的错误是strpos()返回匹配的索引,为0。0被强制转换为布尔值false,因此条件实际上为真。解决方案是使用===而不是==来避免隐式转换。

这个例子说明了隐式转换和动态类型的组合是如何使程序员误入歧途的。

与Ruby相比:

val = "abc" + 123

这是一个运行时错误,因为在Ruby中,对象 123被隐式转换为,因为它恰好被传递给+方法。在Ruby中,程序员必须明确转换:

val = "abc" + 123.to_s

比较PHP和Ruby是一个很好的例子。两者都是动态类型语言,但PHP有很多隐式转换,而Ruby(如果您不熟悉它,可能会感到惊讶)没有。

静态/动态vs强/弱

这里的重点是静态/动态轴独立于强/弱轴。人们混淆它们的部分原因可能是强类型和弱类型不仅定义不明确,而且对于强类型和弱类型的确切含义也没有真正的共识。因此,强/弱类型更像是灰色的阴影,而不是黑色或白色。

所以回答你的问题:另一种看待主要是正确的方法是说静态类型是编译时类型安全,强类型是运行时类型安全。

原因是静态类型语言中的变量具有必须声明的类型,并且可以在编译时进行检查。强类型语言的值在运行时具有类型,如果没有动态检查,程序员很难破坏类型系统。

但重要的是要理解一种语言可以是静态/强、静态/弱、动态/强或动态/弱。

一个并不意味着另一个。对于静态类型的语言,这意味着所有变量的类型都是在编译时已知或推断出来的。

强烈类型语言不允许您将一种类型用作另一种类型。C是一种弱类型语言,是强类型语言不允许的一个很好的例子。在C语言中,你可以传递错误类型的数据元素,它不会报错。在强类型语言中你不能这样做。

两者都是两个不同轴上的极点:

  • 强类型与弱类型
  • 静态类型vs.动态类型

强类型表示变量不会自动从一种类型转换为另一种类型。弱类型则相反:Perl可以在数值上下文中使用"123"这样的字符串,方法是自动将其转换为int 123。像python这样的强类型语言不会这样做。

静态类型表示编译器在编译时计算出每个变量的类型。动态类型语言只在运行时确定变量的类型。

强类型可能意味着变量具有定义良好的类型,并且对于在表达式中组合不同类型的变量有严格的规则。例如,如果A是一个整数,B是一个浮点数,那么关于A+B的严格规则可能是A被强制转换为浮点数,并且结果作为浮点数返回。如果A是一个整数,B是一个字符串,那么严格的规则可能是A+B无效。

静态类型可能意味着类型是在编译时分配的(或非编译语言的等效类型),并且在程序执行期间不能更改。

请注意,这些分类并不相互排斥,实际上我希望它们经常一起出现。许多强类型语言也是静态类型的。

请注意,当我使用“可能”这个词时,是因为这些术语没有普遍接受的定义。到目前为止,你已经从答案中看到了。

数据强制并不一定意味着弱类型,因为有时它的语法糖:

上面Java的例子是弱类型的,因为

String s = "abc" + 123;

不是弱类型的例子,因为它真正做的是:

String s = "abc" + new Integer(123).toString()

如果您正在构造一个新对象,数据强制也不是弱类型的。 Java是弱类型的一个非常糟糕的例子(任何具有良好反射的语言都很可能不是弱类型的)。因为语言的运行时总是知道类型是什么(异常可能是本机类型)

这与C不同。C是弱类型的最佳示例之一。运行时不知道4字节是整数、结构体、指针还是4个字符。

语言的运行时真正定义了它是否弱类型,否则它只是意见。

< p >编辑: 经过进一步思考,这并不一定是正确的,因为运行时不必在运行时系统中具体化所有类型,以成为强类型系统。 Haskell和ML有这样完整的静态分析,它们可以潜在地从运行时提交类型信息。< / em > < / p >

强类型语言和静态类型语言的区别是什么?

静态类型语言具有在编译时由实现(编译器或解释器)检查的类型系统。类型检查拒绝一些程序,通过检查的程序通常带有一些保证;例如,编译器保证不对浮点数使用整数算术指令。

对于“强类型”的含义并没有真正的共识,尽管在专业文献中使用最广泛的定义是,在“强类型”语言中,程序员不可能绕过类型系统施加的限制。这个术语几乎总是用来描述静态类型的语言。

静态vs动态

静态类型的反面是“动态类型”,这意味着

  1. 在运行时使用的值被分为不同的类型。
  2. 对于如何使用这些值有一些限制。
  3. 当违反这些限制时,违反将作为(动态)类型错误报告。

例如,Lua是一种动态类型语言,它具有字符串类型、数字类型和布尔类型等。在Lua中,每个值都属于完全这种类型,但这并不是所有动态类型语言都必须这样做。在Lua中,允许连接两个字符串,但不允许连接字符串和布尔值。

强与弱

“强类型”的反义词是“弱类型”,这意味着你可以绕过类型系统。C语言是出了名的弱类型,因为任何指针类型都可以通过强制转换转换为任何其他指针类型。Pascal本来是强类型的,但是设计中的一个疏忽(未标记的变量记录)在类型系统中引入了一个漏洞,所以从技术上讲它是弱类型的。 真正强类型语言的例子包括CLU、Standard ML和Haskell。事实上,标准ML已经经历了几次修订,以消除类型系统中的漏洞,这些漏洞是在语言广泛部署后发现的

这里到底发生了什么?

总的来说,讨论“强”和“弱”并没有那么有用。一个类型系统是否存在漏洞,重要的是漏洞的确切数量和性质,它们在实践中出现的可能性,以及利用漏洞的后果。在实践中,最好避免使用“强”和“弱”这两个词,因为

  • 业余爱好者经常把它们与“静态”和“动态”混为一谈。

  • 显然,有些人用“弱类型”来谈论隐式转换的相对流行或缺乏。

  • 专业人士无法就这些术语的确切含义达成一致。

  • 总的来说,你不太可能告诉或启发你的观众。

可悲的事实是,当涉及到类型系统时,如果你想讨论类型系统的相对强度,最好是讨论到底提供了什么保证,没有提供什么保证。 例如,一个很好的问题是:“是否保证给定类型(或类)的每个值都是通过调用该类型的构造函数之一创建的?”在C中,答案是否定的。在CLU, f#和Haskell中,答案是肯定的。对于c++我不确定,我想知道。< / p >

相反,静态类型意味着程序是执行前检查,程序可能在开始之前就被拒绝。动态类型意味着的类型在的执行中被检查,一个类型糟糕的操作可能会导致程序在运行时停止或发出错误信号。使用静态类型的一个主要原因是排除可能存在这种“动态类型错误”的程序。

两者之间是否有关联?

从学究的角度来说,没有,因为“强大”这个词其实没有任何意义。但实际上,人们几乎总是做两件事中的一件:

  • 他们(不正确地)使用“强”和“弱”来表示“静态”和“动态”,在这种情况下,他们(不正确地)互换使用“强类型”和“静态类型”。

  • 他们使用“强”和“弱”来比较静态类型系统的属性。很少听到有人谈论“强”或“弱”动态类型系统。除了FORTH(它实际上没有任何类型的类型系统),我想不出有哪一种动态类型语言可以颠覆类型系统。根据定义,这些检查被内置到执行引擎中,并且每个操作在执行之前都会被检查是否正常。

不管怎样,如果有人称一种语言为“强类型”,那么这个人很可能是在谈论一种静态类型的语言。

答案已经在上面给出了。试图区分强与周,静态与动态的概念。

什么是强类型VS弱类型?

强类型:不会自动从一种类型转换为另一种类型

在Go或Python这样的强类型语言中,“2”+ 8会引发类型错误,因为它们不允许“类型强制”。

弱(松散)类型:将自动转换为一种类型为另一种类型: 弱类型语言,如JavaScript或Perl不会抛出错误,在这种情况下,JavaScript的结果是'28',Perl的结果是10

Perl的例子:

my $a = "2" + 8;
print $a,"\n";

将其保存到main.pl并运行perl main.pl,您将得到输出10。

什么是静态和动态类型?

在编程中,程序员根据检查变量类型的点来定义静态类型和动态类型。静态类型语言是指在编译时进行类型检查的语言,而动态类型语言是指在运行时进行类型检查的语言。

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

这是什么意思?

在Go中,它在运行前检查输入(静态检查)。这意味着它不仅翻译和类型检查它正在执行的代码,而且它将扫描所有的代码,甚至在代码运行之前就会抛出类型错误。例如,

package main


import "fmt"


func foo(a int) {
if (a > 0) {
fmt.Println("I am feeling lucky (maybe).")
} else {
fmt.Println("2" + 8)
}
}


func main() {
foo(2)
}

在main中保存此文件。去运行它,你会得到编译失败的消息。

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

但这种情况不适用于Python。例如,下面的代码块将在第一次foo(2)调用时执行,而在第二次foo(0)调用时失败。这是因为Python是动态类型的,它只翻译和类型检查它所执行的代码。对于foo(2), else块从未执行,因此“2”+ 8甚至从未被查看,对于foo(0)调用,它将尝试执行该块,但失败。

def foo(a):
if a > 0:
print 'I am feeling lucky.'
else:
print "2" + 8
foo(2)
foo(0)

您将看到以下输出

python main.py
I am feeling lucky.
Traceback (most recent call last):
File "pyth.py", line 7, in <module>
foo(0)
File "pyth.py", line 5, in foo
print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

恕我直言,最好完全避免这些定义,不仅没有一致的术语定义,确实存在的定义倾向于关注技术方面,例如,混合类型上的操作是否允许,如果不允许,是否存在绕过限制的漏洞,例如使用指针工作。

相反,再次强调这是一种观点,人们应该关注这个问题:类型系统是否使我的应用程序更可靠?一个特定于应用程序的问题。

例如:如果我的应用程序有一个名为加速度的变量,那么显然,如果变量的声明和使用方式允许将值“Monday"分配给加速度,这是一个问题,因为显然加速不能是一个工作日(和字符串)。

另一个例子:在Ada中可以定义:subtype Month_Day是整数范围1..31;,类型Month_Day在某种意义上是弱的,因为它不是一个与Integer分离的类型(因为它是一个子类型),但是它被限制在1..31的范围内。相比之下:类型Month_Day是新的整数;将创建一个独特的类型,在没有显式强制转换的情况下它不能与整数混合的意义上是强类型,但它不受限制,可以接收无意义的值-17。所以从技术上讲,它更强,但不太可靠。 当然,可以声明type Month_Day是新的整数范围1..31;来创建一个不同且受限的类型