强类型语言 & 弱类型语言、动态语言 & 静态语言

记得刚开始接触 js 的时候觉得很神奇,因为最开始学的是 C、C++ ,觉得编程先声明变量类型再申请空间,赋值使用,是很理所当然的事情。到了 js 只分 let 、var 和 const 。突然有种 js 更加符合现代化、更加“聪明”的想法。再后面接触到 Python ,连只读和可读写的声明都省了,内部就是很纯粹地在每个 frame 里面用字典来维持变量和对象的关系。回到 Java 又变得要声明类型了。

为什么有些语言看上去那么的“智能”,有些语言就显得“啰嗦”和“笨重”。这当中涉及到强类型语言 & 弱类型语言、动态语言 & 静态语言的几个概念。



强类型语言 & 弱类型语言

如何区分语言类型的强弱,不是看在声明的时候是否需要指定类型,而是看一个变量一旦被指定成某种类型后,不经过强制类型转换,能否自动的被隐式转换成其他数据类型来使用。光听很绕,举例来理解:

这是一段试图将 int 类型的变量不经过强制类型转换当成 str 类型来使用,或者说试图将 str 类型的变量不经过强制类型转换当成 int 类型来使用的 Python 程序(同样是数字和字符串,不同的语言会选择不同的对象来转换,下面会讲到):

1
2
3
4
5
if __name__ == '__main__':
a = int(1)
b = "2"
c = a + b
# c = a + int(b)

在不注释第 4 行代码,打开第 5 行代码时,会报错

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

不能对 int 和 str 变量进行 + 操作,也就是说没有帮我们进行隐式转换,所以 Python 是属于强类型语言

Python 是强类型语言,那有弱类型的语言吗?有, js 就是弱类型语言,同样的还有 PHP ,它们都支持类似以下的隐式转换操作:

1
console.log("1"+2);

执行上面的 js 代码,输出”12”,将数字 2 隐私转换成了字符串,再进行字符串的拼接。

1
2
3
<?php
echo "1"+2;
?>

执行上面的 PHP 代码,输出 3 ,将字符串 “1” 转换成了数字,再进行相加运算。

两种语言都支持隐式类型转换,都属于弱类型语言范畴,只是转换对象不同(也就是我上面说到的“不同语言”)。


说到这里,之前我看过网上不少博客资料,都将 Python 划分到弱类型语言,而他们的依据都是类似下面的代码:

1
2
3
4
if __name__ == '__main__':
a = int(1)
a = "2"
print(a)

这只是将原本指向 int 类型对象的变量 a 重新指向一个 str 类型对象的操作而已,并没有涉及转换问题。这样的代码应该是用于分析语言是静态类型还是动态类型,而不是分析语言是强类型还是弱类型。不过这正好引入将要讲的动态语言 & 静态语言。

进入动态语言 & 静态语言之前,再强调一下:Python 是强类型语言。区分语言的强弱类型的依据是:看语言是否支持隐式类型转换,而不是看声明时是否需要指定类型,更不是看是否能够直接赋值成其他数据类型



动态语言 & 静态语言

如何区分动态语言 & 静态语言,判断的依据应该是看变量是否和具体数据类型相关联,也就是说看编译阶段,是否就已经知道了每个变量的类型,如果知道就是静态语言。反之就是动态语言。还是选择结合例子说明,还是引用刚刚那段 Python 代码:

1
2
3
4
if __name__ == '__main__':
a = int(1)
a = "2"
print(a)

变量 a 刚开始是被指向 int 类型,然后又被重新指向成 str 并被正常使用。说明变量 a 只是和具体对象”绑定“,并没有和具体对象的数据类型”绑定“,它们可以简单描述成这样:a: 对象1(int),a只和对象1关联,具体的类型信息是被包含到对象1中,和变量 a 本身没有关系。当被重新指向的时候,变量 a 直接和对象1“解绑”,与对象2“绑定”,关系修改为:a: 对象2(str)。也就是说 Python 在编译阶段是没有办法确定某个变量的数据类型的(没错,Python 也是需要被编译的),说以 Python 是一门动态语言

而对于 C 语言来说:

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdlib.h>

int main() {
int a = 1;
char* b = "abc";

int c;
c = a;
c = b;

return 0;
}

当执行 int c; 的时候,变量 c 就已经和数据类型强关联了,以后也只能装载 int 类型的数据。它们的关系可以描述成:c:int + c:1,c 既跟数据类型关联,也跟具体的值关联。而且当我们修改变量 c 的时候,只能修改后一层关系,而不能前一层变量和数据类型的关系。所以结论是 C 在编译阶段就可以完全确定某个变量对应数据类型是什么,C 是一门静态语言

总结一下,区分一门语言是静态语言还是动态语言要看该语言是否能在编译阶段确定所有变量的数据类型,如果可以就是一门静态语言,反之就是动态语言



强类型语言 & 弱类型语言、动态语言 & 静态语言,有优劣之分吗?

弱类型语言由于支持隐式转换,一定程度下,出错概率要比强类型要低。但是同样的,优点在某些情况会成为隐患,不抛异常会导致难以发现错误,甚至程序会在隐式转换后以不是我们期望的方式一直往下执行,引发重大问题。而强类型语言则会将错误扼杀在摇篮,但是无法省去强制类型转换的代码,让本来像名画一样优雅的代码多了一些”星星点点“。

静态语言和动态语言的选择更多的是性能和安全性之前的权衡。静态语言的性能要比动态语言的低,因为每次执行都少不了先进行数据类型的检查,动态语言则是直接执行,省去了很多前置判断,如果因为数据类型不对执行出错了再抛异常。

所以强类型语言 & 弱类型语言、动态语言 & 静态语言之间其实没有优劣之分,只是侧重点不同的权衡结果。



各种主流语言强弱和动静

强类型语言:Python、Ruby、C#、Java

弱类型语言:C、C++、js、PHP

动态语言:Python、Ruby、js、PHP

静态语言:C、C++、C#、Java

Java Web Servlet 体系结构(一) Java Web Servlet 快速入门

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×