首页 文章

静态类型语言和动态类型语言有什么区别?

提问于
浏览
738

我听到很多新的编程语言是动态类型的,但是当我们说一种语言是动态类型而非静态类型时,它实际意味着什么呢?

15 回答

  • 39

    Static Typing: Java和Scala等语言是静态类型的 .

    必须在代码中使用变量之前定义和初始化变量 .

    对于前int x; x = 10;

    的System.out.println(X);

    Dynamic Typing: Perl是一种动态类型语言 .

    在代码中使用变量之前,无需初始化变量 .

    Y = 10;在代码的后半部分使用此变量

  • 1

    静态类型编程语言在编译时进行类型检查(即验证和强制执行类型约束的过程),而不是运行时 .

    动态类型编程语言在运行时进行类型检查而不是编译时 .

  • 1

    静态类型语言

    如果在编译时已知变量的类型,则静态键入语言 . 对于某些语言,这意味着您作为程序员必须指定每个变量的类型(例如:Java,C,C);其他语言提供某种形式的类型推断,类型系统推断变量类型的能力(例如:OCaml,Haskell,Scala,Kotlin)

    这里的主要优点是所有类型的检查都可以由编译器完成,因此在很早的阶段就会发现许多琐碎的错误 .

    动态键入的语言

    如果类型与运行时值相关联,则动态类型化语言,而不是命名变量/字段/等 . 这意味着您作为程序员可以更快地编写,因为您不必每次都指定类型(除非使用带类型推断的静态类型语言) . 示例:Perl,Ruby,Python

    大多数脚本语言都具有此功能,因为无论如何都没有编译器进行静态类型检查,但您可能会发现自己正在搜索由于解释器错误解释变量类型而导致的错误 . 幸运的是,脚本往往很小,所以bug没有那么多地方可以隐藏 .

    大多数动态类型语言都允许您提供类型信息,但不需要它 . 目前正在开发的一种语言Rascal采用混合方法,允许在函数内动态键入,但强制执行函数签名的静态类型 .

  • 14

    下面是一个示例,对比Python(动态类型)和Go(静态类型)如何处理类型错误:

    def silly(a):
        if a > 0:
            print 'Hi'
        else:
            print 5 + '3'
    

    Python在运行时进行类型检查,因此:

    silly(2)
    

    运行完全正常,并产生预期的输出 Hi . 只有在遇到有问题的行时才会引发错误:

    silly(-1)
    

    产生

    TypeError:不支持的操作数类型:'int'和'str'

    因为相关的线路实际上已经执行了 .

    另一方面,在编译时进行类型检查:

    package main
    
    import ("fmt"
    )
    
    func silly(a int) {
        if (a > 0) {
            fmt.Println("Hi")
        } else {
            fmt.Println("3" + 5)
        }
    }
    
    func main() {
        silly(2)
    }
    

    以上将无法编译,并出现以下错误:

    无效操作:“3”5(不匹配的类型字符串和int)

  • -13

    简单地说就是这样:在 statically typed language 变量中,类型是静态的,这意味着一旦将变量设置为类型,就无法更改它 . 这是因为键入与变量而不是它所引用的值相关联 .

    例如在Java中:

    String str = "Hello";  //variable str statically typed as string
    str = 5;               //would throw an error since str is supposed to be a string only
    

    另一方面:在 dynamically typed language 变量中,变量的类型是动态的,这意味着在将变量设置为类型后,您可以更改它 . 这是因为打字与它所假定的值相关联,而不是与变量本身相关联 .

    例如在Python中:

    str = "Hello" # variable str is linked to a string value
    str = 5       # now it is linked to an integer value; perfectly OK
    

    因此,最好将动态类型语言中的变量视为键入值的通用指针 .

    总而言之, type 描述(或应该描述)语言中的变量而不是语言本身 . 它本来可以更好地用作 a language with statically typed variablesa language with dynamically typed variables 恕我直言 .

    静态类型语言通常是编译语言,因此,编译器检查类型(完美正确吗?因为类型不允许稍后在运行时更改) .

    通常会解释动态类型语言,因此在使用它们时会在运行时进行类型检查(如果有) . 这当然会带来一些性能成本,并且是动态语言(例如,python,ruby,php)不能像键入的那些(java,c#等)那样扩展的原因之一 . 从另一个角度来看,静态类型语言具有更多的启动成本:使您通常编写更多代码,更难编写代码 . 但是后来付出了代价 .

    好处是双方都在借用另一方的特征 . 类型化语言包含更多动态特性,例如c#中的泛型和动态库,动态语言包括更多类型检查,例如python中的类型注释,或PHP的HACK变体,它们通常不是语言的核心,可用于需求 .

    在技术选择方面,任何一方都没有内在的优势 . 无论您是想要更多控制还是灵活性,这只是一个偏好问题 . 只需为工作挑选合适的工具,并确保在考虑开关之前检查相反的可用工具 .

  • 5

    http://en.wikipedia.org/wiki/Type_system

    静态类型编译语言在编译时执行类型检查时使用静态类型而不是运行 . 在静态类型中,类型与变量而不是值相关联 . 静态类型语言包括Ada,C,C,C#,JADE,Java,Fortran,Haskell,ML,Pascal,Perl(关于区分标量,数组,散列和子例程)和Scala . 静态类型是一种有限形式的程序验证(参见类型安全性):因此,它允许在开发周期的早期捕获许多类型错误 . 静态类型检查器仅评估可在编译时确定的类型信息,但能够验证检查的条件是否适用于程序的所有可能执行,这消除了每次执行程序时重复类型检查的需要 . 通过省略运行时类型检查并启用其他优化,也可以使程序执行更有效(即更快或减少内存) . 因为它们在编译期间评估类型信息,因此缺少仅在运行时可用的类型信息,所以静态类型检查器是保守的 . 他们会拒绝一些在运行时可能表现良好的程序,但这些程序无法通过静态确定为良好类型 . 例如,即使表达式在运行时始终求值为true,程序包含代码,如果<complex test>则42 else <type error>
    因为静态分析无法确定不会采取其他分支,因此将被拒绝作为错误类型 . [1]静态类型检查器的保守行为在不经常评估为错误时是有利的:静态类型检查器可以检测很少使用的代码路径中的类型错误 . 如果没有静态类型检查,即使具有100%代码覆盖率的代码覆盖率测试也可能无法找到此类型错误 . 代码覆盖率测试可能无法检测到此类型错误,因为必须考虑创建值的所有位置和使用特定值的所有位置的组合 . 最广泛使用的静态类型语言不是正式类型安全的 . 它们在编程语言规范中存在“漏洞”,使程序员能够编写绕过静态类型检查器执行的验证的代码,从而解决更广泛的问题 . 例如,Java和大多数C风格的语言具有类型惩罚,而Haskell具有诸如unsafePerformIO之类的功能:这样的操作在运行时可能是不安全的,因为它们可能由于在程序运行时错误地键入值而导致不希望的行为 . 动态类型当编程语言的大多数类型检查是在运行时而不是在编译时执行时,它被称为动态类型,或者只是“动态” . 在动态类型中,类型与值而不是变量相关联 . 动态类型语言包括Groovy,JavaScript,Lisp,Lua,Objective-C,Perl(关于用户定义类型但不是内置类型),PHP,Prolog,Python,Ruby,Smalltalk和Tcl . 与静态类型相比,动态类型可以更灵活(例如,通过允许程序基于运行时数据生成类型和功能),但代价是先验保证较少 . 这是因为动态类型语言接受并尝试执行某些程序,这些程序可能被静态类型检查器判定为无效 . 动态类型可能导致运行时类型错误 - 即,在运行时,值可能具有意外类型,并且应用对该类型无意义的操作 . 这种操作可能在编程错误发生的地方很久之后发生 - 也就是说,错误类型的数据传递到它不应该具有的地方的地方 . 这使得很难找到错误 . 动态类型语言系统与其静态类型的同类相比,对源代码进行的“编译时”检查更少(但会检查,例如,程序在语法上是否正确) . 运行时检查可能更复杂,因为它们可以使用动态信息以及编译期间出现的任何信息 . 另一方面,运行时检查仅断言条件在程序的特定执行中保持,并且对于程序的每次执行都重复这些检查 . 动态类型语言的开发通常由单元测试等编程实践支持 . 测试是专业软件开发中的关键实践,在动态类型语言中尤为重要 . 实际上,为确保正确的程序操作而进行的测试可以检测到比静态类型检查更广泛的错误,但相反地,不能全面地搜索测试和静态类型检查能够检测到的错误 . 测试可以合并到软件构建周期中,在这种情况下,它可以被认为是“编译时”检查,因为程序用户不必手动运行这样的测试 . 参考文献Pierce,Benjamin(2002) . 类型和编程语言 . MIT出版社 . 国际标准书号0-262-16209-1 .

  • 284

    遗憾的是,术语“动态类型化”误导 . 所有语言都是静态类型的,类型是表达式的属性(不像某些人认为的那样是值) . 但是,某些语言只有一种类型 . 这些被称为单类型语言 . 这种语言的一个例子是无类型的lambda演算 .

    在无类型lambda演算中,所有术语都是lambda术语,并且可以对术语执行的唯一操作是将其应用于另一个术语 . 因此,所有操作总是导致无限递归或lambda术语,但从不发出错误信号 .

    但是,如果我们用原始数和算术运算来扩充无类型lambda演算,那么我们可以执行无意义的操作,例如将两个lambda项一起添加: (λx.x) + (λy.y) . 有人可能会争辩说,唯一明智的做法就是在发生这种情况时发出错误信号,但为了能够做到这一点,每个值都必须用一个指示符来标记,该指示符指示该术语是lambda术语还是数字 . 然后,加法运算符将检查两个参数是否都被标记为数字,如果不是,则表示错误 . 请注意,这些标记不是类型,因为类型是程序的属性,而不是这些程序生成的值 .

    执行此操作的单类型语言称为动态类型 .

    JavaScript,Python和Ruby等语言都是单类型的 . 同样,JavaScript中的 typeof 运算符和Python中的 type 函数具有误导性的名称;它们返回与操作数关联的标记,而不是它们的类型 . 类似地,C中的 dynamic_cast 和Java中的 instanceof 不进行类型检查 .

  • 131

    静态类型语言在编译时进行类型检查,类型不能更改 . (对于类型转换注释不要太可爱,创建一个新的变量/引用) .

    动态类型语言在运行时进行类型检查,并且可以在运行时更改变量的类型 .

  • 660

    编译与解释

    “当源代码被翻译时”

    • Source Code :原始代码(通常由人类输入计算机)

    • Translation :将源代码转换为计算机可以读取的内容(即机器代码)

    • Run-Time :程序执行命令的时间段(编译后,如果编译)

    • Compiled Language :在运行时之前翻译的代码

    • Interpreted Language :代码在执行期间即时翻译


    打字

    “检查类型时”

    5 + '3' 是强类型语言(如Go和Python)中类型错误的一个示例,因为它们不允许值在某些上下文中更改类型,例如合并两种类型 . 弱类型语言(如JavaScript)不会引发类型错误(导致 '53' ) .

    • Static :在运行时检查的类型

    • Dynamic :执行期间动态检查的类型


    “静态与编译”和“动态与解释”的定义非常相似......但请记住“当检查类型时”与“源代码翻译时” .

    You'll get the same type errors irrespective of whether the language is compiled or interpreted !您需要在概念上区分这些术语 .


    Python示例

    动态,解释

    def silly(a):
        if a > 0:
            print 'Hi'
        else:
            print 5 + '3'
    
    silly(2)
    

    因为Python既被解释又被动态地键入,它只对它正在执行的代码进行转换和类型检查 . else 块永远不会执行,因此 5 + '3' 永远不会被查看!

    如果是静态输入怎么办?

    在代码运行之前会抛出类型错误 . 它仍然在运行时执行类型检查,即使它被解释 .

    怎么编译呢?

    else 块将在运行时之前进行转换/查看,但因为它会抛出错误!动态类型语言在执行之前不会检查类型,并且该行永远不会执行 .


    Go Example

    静态,编译

    package main
    
    import ("fmt"
    )
    
    func silly(a int) {
      if (a > 0) {
          fmt.Println("Hi")
      } else {
          fmt.Println("3" + 5)
      }
    }
    
    func main() {
      silly(2)
    }
    

    在运行之前检查类型(静态),并立即捕获类型错误!如果解释了类型,则在运行时仍然会检查这些类型,结果相同 . 如果它是动态的,即使在编译期间查看代码,它也不会抛出任何错误 .


    表现

    如果编译语言是静态类型(动态对比),则它在运行时将具有更好的性能;类型知识允许机器代码优化 .

    静态类型语言在运行时本质上具有更好的性能,因为在执行时不需要动态检查类型(它在运行之前检查) .

    类似地,编译语言在运行时更快,因为代码已经被翻译而不是需要动态地“解释”/翻译它 .

    请注意,编译和静态类型语言在运行转换和类型检查之前都会有延迟 .


    更多差异

    静态类型提前捕获错误,而不是在执行期间找到它们(对于长程序尤其有用) . 它更“严格”,因为它不会在程序中的任何地方出现类型错误,并且通常会阻止变量更改类型进一步防止意外错误 .

    num = 2
    num = '3' // ERROR
    

    动态类型更灵活,有些人欣赏 . 它通常允许变量更改类型,这可能导致意外错误 .

  • 4

    简单明了的定义,但符合需要:静态类型语言将类型绑定到整个范围的变量(Seg:SCALA)动态类型语言将类型绑定到变量引用的实际值 .

  • 5
    • 在静态类型语言中,变量与在编译时已知的类型相关联,并且该类型在程序执行期间保持不变 . 等价地,只能为变量分配一个值,该值是已知/指定类型的实例 .

    • 在动态类型语言中,变量没有类型,并且在执行期间它的值可以是任何形状和形式的任何值 .

  • 0

    静态类型语言(如C,Java)和动态类型语言(如Python)的区别仅在于变量类型的执行 . Statically typed 语言具有变量的静态数据类型,这里在编译期间检查数据类型,因此调试更简单...而 Dynamically typed 语言不执行相同操作,检查执行程序的数据类型,因此调试是有点困难 .

    此外,它们的差异非常小,可以与 strongly typedweakly typed 语言相关联 . 强类型语言不允许您将一种类型用作另一种类型 . C和C ......而弱类型语言允许eg.python

  • 0

    Statically typed languages :每个变量和表达式在编译时都已知 .

    int a; a在运行时只能取整数类型值)

    示例:C,C,Java

    Dynamically typed languages :变量可以在运行时接收不同的值,并且它们的类型是在运行时定义的 .

    var a; a可以在运行时获取任何类型的值)

    示例:Ruby,Python .

  • 249

    dynamically typed language 有助于快速 Build 算法概念原型,而无需考虑需要使用哪些变量类型(这在 statically typed languag 中是必需的) .

  • 3

    你能在官方网站上看到:Click here

相关问题