一文搞懂语言的静态类型动态类型强类型弱类型编译型解释型

Posted Weber77

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文搞懂语言的静态类型动态类型强类型弱类型编译型解释型相关的知识,希望对你有一定的参考价值。

首先我们先从我们一个经常使用的语言入手,来探讨语言的各种分类。

比如说我最近在学习的golang,官方对他的定义是

 Go is statically typed, explicit and modeled after the C programming language.

对explicit的解释如下

Explicit language is language that is fully and clearly expressed or formulated,

 leaving nothing implied or ambiguous

我们可以知道go是一个静态显式的语言,而显式则意味着该语言的定义和表达是清楚明了的,我们在这里可以简单的理解为go定义的任何单元都需要有明确的类型,可以简单的理解为对静态类型的解释。

同时我们又知道我们在编写go语言程序时,代码会保存在xxxx.go文件下,我们执行go bulid xxxx.go,生成当前操作系统下可执行文件,在执行可执行文件;以上的步骤等同于go run xxxx.go。所以go是一种编译型语言。

Golang是一种静态强类型,编译型语言

我们在举一个Java的例子,官方给出的解释是Java是一种静态强类型语言,但是在编译型还是解释型语言上大家产生了分歧,我们首先回顾Java代码完成到执行这段时间发生了什么

 

首先xxx.java会被javac编译器编译成xxx.class的字节码文件,之后字节码文件会被JVM根据操作系统的不同解释成操作系统可以理解的机器码并运行出结果。

根据以上我们可以看出并不能单纯的把Java定义为编译型语言或解释型语言,现在大部分人认为Java是一种半编译半解释型语言,由于编译型和解释型的分类并不能很好的对语言分类,所以现在这种语言分类以及逐渐退出历史舞台。

 Java是一种静态强类型,半编译型半解释型语言


编译型语言和解释型语言

通过高级语言编写的源码,我们能够轻松理解,但对于计算机来说,它只认识二进制指令,源码就是天书,根本无法识别。源码要想执行,必须先转换成二进制指令。

然而,究竟在什么时候将源代码转换成二进制指令呢?不同的编程语言有不同的规定:

  • 有的编程语言要求必须提前将所有源代码一次性转换成二进制指令,也就是生成一个可执行程序(比如 Windows 下的 .exe 文件),比如C语言、C++、Golang、汇编语言等,它们都属于编译型语言,使用的转换工具称为编译器
  • 有的编程语言可以一边执行一边转换,需要哪些源代码就转换哪些源代码,不会生成可执行程序,比如 PythonJavaScriptPHP、Shell 等,这类编程语言称为解释型语言,使用的转换工具称为解释器

简单地理解,编译器和解释器其实就是一个“翻译工具”,对源代码进行“翻译”是一个很复杂的过程,大致包括词法分析、语法分析、语义分析、性能优化、生成可执行文件等五个步骤。

编译型语言和解释型语言的执行流程如下所示:

编译型语言

对于编译型语言,开发完成以后需要将所有的源代码都转换成可执行程序,比如 Windows 下的.exe文件就是一个可执行程序,它里面包含的就是机器码,只要拥有这个可执行程序,就可以随时运行,不需要再重新编译,也就是“一次编译,无限次运行”

在运行的时候,我们只需要编译生成的可执行程序,此时就不再需要源代码和编译器,所以编译型语言可以脱离开发环境运行。

编译型语言通常是不能跨平台的,也就是不能在不同的操作系统之间随意切换。

优点:编译器一般会有预编译的过程对代码进行优化。因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高。可以脱离语言环境独立运行。

缺点:编译之后如果需要修改就需要整个模块重新编译。编译的时候根据对应的运行环境生成机器码,不同的操作系统之间移植就会有问题,需要根据运行的操作系统环境编译不同的可执行文件。

代表语言:C、C++、Golang、Pascal、swift

解释型语言

对于解释型语言,每次执行程序都需要一边转换一边执行,用到哪些源代码就将哪些源代码转换成机器码,用不到的则不进行任何处理。

相比于编译型语言,解释型语言几乎都能跨平台,“一次编写,到处运行”是真实存在的,而且比比皆是。

优点:有良好的平台兼容性,在任何环境中都可以运行,前提是安装了解释器(虚拟机)。灵活,修改代码的时候直接修改就可以,可以快速部署,不用停机维护。

缺点:每次运行的时候都要解释一遍,性能上不如编译型语言。

代表语言:javascript、Python、php、Ruby

类型原理优点缺点
编译型语言通过专门的编译器,将所有源代码一次性转换成特定平台(Windows、Linux、macOS等)的机器码(以可执行文件的形式存在)。编译一次后,脱离了编译器也能运行,并且运行效率高。可移植性差,不够灵活。
解释型语言通过专门的解释器,根据需要可以将部分或全部源代码转换成特定平台(Windos、Linux、macOS等)的机器码。跨平台性好,通过不同的解释器,将相同的源代码解释成不同平台下的机器码。一边执行一边转换,效率较低。
 

静态类型和动态类型

静态类型

静态类型语言中,变量的类型必须先声明,即在创建的那一刻就已经确定好变量的类型,而后的使用中,你只能将这一指定类型的数据赋值给变量。如果强行将其他不相干类型的数据赋值给它,就会引发错误。

静态语言是编译期间做检查数据类型的语言,即写程序时要声明所有变量的数据类型,是固定的。使用数据之前,必须先声明数据类型(int ,float,double等)。相当于使用之前,首先要为它们分配好内存空间。

例如:Java、C、Golang、C++

优点:结构非常规范,便于调试,方便类型安全

缺点:为此需要写更多类型相关代码,较复杂。

动态语言

运行期间才做数据类型检查的语言,即动态类型语言编程时,永远不用给任何变量指定数据类型。该语言会在第一次赋值给变量时,在内部将数据类型记录下来。

例如:Python、PHP、Ruby

优点:方便阅读,不需要写非常多的类型相关的代码;

缺点:不方便调试,命名不规范时会造成读不懂,不利于理解等。


强类型和弱类型

强弱之分,体现在对类型的检查严格程度上,弱类型语言对于变量类型的检查比较宽松,容忍隐式类型转换这种事情的发生。何为隐式类型转换,一般有两种形式:

  1. 相关类型之间隐式转换
  2. 不相关类型之隐式间转换

举例子来说,一个int类型的数据与一个float类型的数据相加,最终的结果是一个float类型的数据,这个过程就发生了隐式类型转换,int类型数据首先被转成float类型,然后与另一个float进行操作,这便是相相关类型之间隐式转换。

一个int类型数据与一个字符串类型数据相加,竟然没有发生错误,得到的结果是一个字符串,int类型数据隐式转换为字符串,可他们原本是两个不相干的数据类型,这种就是第二种隐式转换。

强类型

强制数据类型定义的语言。也就是说,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。

例如:Java、Python、Golang

弱类型

数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。

例如:C、PHP、JS


下面是一张图对大部分语言的分类

强类型和弱类型,静态类型和动态类型语言如何区分

强类型和弱类型

如果一门语言很少隐式转换类型,说明他是强类型语言。如果经常这么做,说明他是弱类型语言。java, c++和python是强类型语言。PHP,JavaScript和Perl是弱类型语言

静态类型和动态类型

在编译时检查类型的语言是静态类型语言,在运行时检查类型的语言是动态语言。静态类型需要声明类型。Fortran和Lisp是最早的两门语言。他们分别是静态类型语言和动态类型语言。

静态类型使得一些工具编译器和ide便于分析代码,找出错误和提供其他服务(优化,重构,等等)。动态类型便于代码重用,代码行数更少,而且能让接口自然成为协议而不提早实行。

以上是关于一文搞懂语言的静态类型动态类型强类型弱类型编译型解释型的主要内容,如果未能解决你的问题,请参考以下文章

python——静态语言动态语言强类型语言弱类型语言脚本语言解释型语言编译型语言

强类型语言/弱类型语言动态语言/静态语言编译型语言/解释型语言(整理)

强类型和弱类型,静态类型和动态类型语言如何区分

编译型与解释型动态语言与静态语言强类型语言与弱类型语言的区别

解释型语言和编译型语言弱类型语言和强类型语言动态语言和静态语言的区别

强/若类型语言 动/静态语言