我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
查看源代码

强弱类型、动静类型、GC 和 VM

强类型 Vs. 弱类型

  • 强和弱是一个相对的概念,强是指倾向于将未定义的行为视作错误(Java、Python),弱是指倾向于进行隐式的转换、忽略类型相关的错误(JavaScript)。
  • 很多设计得不够严谨的语言,虽然大多数情况下(或者我们通常鼓励大家这么做)是强类型的,但也有弱类型的部分(PHP)
  • 还有的语言因为提供的抽象能力很弱,我们不得不去用弱类型的部分(C)
  • 鸭子类型(duck typing)是强弱类型的一个折中(常见于动态类型中,例如 Python),兼顾了灵活性和严谨性。
  • 我们认为弱类型是为了方便,而强类型是为了尽早发现错误。

动态类型 Vs. 静态类型

  • 静态类型的变量的类型是在编译时确定的(C++、Java);动态类型的类型是在运行时确定的(JavaScript、Python),例如你可以在一个 if 的两个分支里给一个变量赋值不同的类型。
  • 有的动态类型语言也会添加编译期的类型检查(TypeScript、Python),但因为语言本身的动态性,这些检查仅能覆盖一部分情况。
  • 在动态类型的语言中因为类型不那么重要,所以很多时候甚至没有提供指定类型的语法(隐含了运行时的自动推导);而在静态类型语言里通常需要为变量指定类型,所以才有了编译期自动类型推导来提供便利,而动态类型语言则做不到这一点(因为不能在编译期确定类型,更无从推导)。
  • 我们认为静态类型有助于在编译时发现有关类型的错误,确定的类型也给了编译期更多的优化空间;而动态类型给了开发者更高的灵活度。

垃圾回收 Vs. 无垃圾回收

  • 无 GC 是指代码必须自行管理申请到的内存并在恰当的时机释放(Rust、C/C++);而有 GC 的语言会通过引用计数(PHP<5.3)、标记复制(V8)等方式定期查找无用的内存进行释放。
  • 标记复制的 GC 的过程通常会引起线程的暂停,也会花费额外的 CPU;但 GC 对于建立高层次的抽象又是必不可少的:异常、闭包等(虽然 C++ 在无 GC 的情况下也实现了这两个特性,但也引入了非常高的复杂度)。
  • 我们认为有 GC 可以简化对内存的管理,建立复杂的抽象;而无 GC 可以得到更底层的对内存的控制,带来更好的性能,避免因为 GC 造成的卡顿。

虚拟机 VS. 本地代码

  • 虚拟机是指在语言和 CPU 之间还有一个用于进行翻译的层次(JavaScript、Java);无虚拟机是指编译器直接生成本地代码给 CPU 执行(C/C++、Golang)。
  • 虚拟机也提供了更为复杂的运行时的动态特性,但这些特性有的时候也可以在没有虚拟机的情况下实现(例如 C++ 的运行时类型识别、Go 的 GC)。
  • 虚拟机可以以解释的方式执行(Python,将代码视作一种数据指令来执行),也可以即时编译(JIT)的方式来执行(V8,先将代码编译到本地代码然后执行),有时也会混合这两种方式(为了更快的启动速度)。
  • 我们认为无虚拟机的语言可以在更低的层次和其他程序交互,同时也天然地有着更好的性能;而有虚拟机的语言则可以轻松地跨平台,针对特定的架构在运行时即时编译出更高性能的代码。

小结

语言 强类型 动态类型 垃圾回收 虚拟机
C
C++ Y
Java Y Y Y
Python Y Y Y Y
JavaScript Y Y Y
PHP Y Y Y
Golang Y Y
Rust Y

参考来源:

撰写评论

如希望撰写评论,请发邮件至 jysperm@gmail.com 并注明文章标题,我会挑选对读者有价值的评论附加到文章末尾。

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.