关于类型安全:强类型语言和静态类型语言有什么区别?

What is the difference between a strongly typed language and a statically typed language?

另外,一个暗示了另一个吗?


What is the difference between a strongly typed language and a statically typed language?

Ok.

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

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

与静态类型相反的是"动态类型",这意味着好的。

  • 在运行时使用的值被分类为类型。
  • 对于如何使用这些值有一些限制。
  • 当违反这些限制时,违规行为将报告为(动态)类型错误。
  • 例如,Lua是一种动态类型语言,它具有字符串类型、数字类型和布尔类型等。在Lua中,每个值只属于一种类型,但这不是所有动态类型语言的要求。在Lua中,允许连接两个字符串,但不允许连接一个字符串和一个布尔值。好的。强VS弱

    与"强类型"相反的是"弱类型",这意味着您可以围绕类型系统工作。C是众所周知的弱类型,因为任何指针类型都可以通过强制转换转换为任何其他指针类型。Pascal被设计为强类型,但是设计中的一个疏忽(未标记的变体记录)给类型系统带来了一个漏洞,因此在技术上它是弱类型的。真正强类型语言的例子包括CLU、标准ML和Haskell。实际上,标准ML已经进行了几次修改,以消除在广泛部署该语言之后发现的类型系统中的漏洞。好的。这里到底发生了什么?

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

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

    • 显然,"弱类型"被一些人用来谈论相对优势或缺乏内隐转换。好的。

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

    • 总的来说,你不太可能通知或启发你的听众。好的。

    可悲的事实是,当涉及到类型系统时,"强"和"弱"并没有一个普遍认同的技术含义。如果您想讨论类型系统的相对强度,最好确切地讨论什么是担保,什么是不担保。例如,要问的一个好问题是:"给定类型(或类)的每个值是否都是通过调用该类型的构造函数之一而创建的?"在C中,答案是否定的。在CLU、F和Haskell中,答案是肯定的。对于C++,我不确定,我想知道。好的。

    相比之下,静态类型意味着程序在执行之前会被检查,并且程序在启动之前可能会被拒绝。动态类型化意味着在执行期间检查值的类型,而类型化不好的操作可能导致程序停止,或者在运行时发出错误信号。静态类型的一个主要原因是排除可能有这样的"动态类型错误"的程序。好的。

    Does one imply the other?

    Ok.

    在学究的层面上,不,因为"强"这个词实际上并不意味着什么。但实际上,人们几乎总是做两件事之一:好的。

    • 他们(错误地)使用"强"和"弱"来表示"静态"和"动态",在这种情况下,他们(错误地)使用"强类型"和"静态类型"可以互换。好的。

    • 他们使用"强"和"弱"来比较静态类型系统的特性。很少有人谈论"强"或"弱"的动态类型系统。除了forth之外,它实际上没有任何类型的系统,我想不出一种动态类型语言,在这种语言中类型系统可以被颠覆。根据定义,这些检查被构建到执行引擎中,并且在执行之前检查每个操作的健全性。好的。

    不管怎样,如果一个人将一种语言称为"强类型",那么他很可能正在谈论一种静态类型的语言。好的。好啊。


    这经常被误解,所以让我澄清一下。好的。静态/动态类型

    静态类型是类型绑定到变量的位置。在编译时检查类型。好的。

    动态类型是类型绑定到值的位置。在运行时检查类型。好的。

    所以在Java中,例如:好的。

    1
    String s ="abcd";

    s将"永远"成为String。在它的生命周期中,它可能指向不同的Strings(因为EDCOX1〔0〕是Java中的参考)。它可能有一个null值,但它不会指IntegerList。这是静态类型。好的。

    在PHP中:好的。

    1
    2
    3
    4
    $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中:好的。

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

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

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

    考虑一个经典的PHP"以开头"问题:好的。

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

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

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

    与Ruby相比:好的。

    1
    val ="abc" + 123

    这是一个运行时错误,因为在Ruby中,对象123没有被隐式转换,只是因为它恰好被传递到+方法。在Ruby中,程序员必须使转换显式化:好的。

    1
    val ="abc" + 123.to_s

    这里比较PHP和Ruby是一个很好的例子。这两种语言都是动态类型的语言,但是PHP有很多隐式转换,而Ruby(如果您不熟悉它,可能会令人惊讶)没有。好的。静态/动态与强/弱

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

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

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

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


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

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

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

    静态类型意味着编译器在编译时计算出每个变量的类型。动态类型语言只在运行时计算出变量的类型。


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

    由于Java的弱类型,上面的例子

    1
    String s ="abc" + 123;

    不是弱类型示例,因为它确实在执行以下操作:

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

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

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

    该语言的运行时确实定义了它是否弱类型化,否则它实际上只是一种意见。

    编辑:在进一步考虑之后,这不一定是真的,因为运行时不需要将运行时系统中的所有类型都重新定义为强类型系统。haskell和ml有如此完整的静态分析,它们可以从运行时获得OMmit类型的潜在信息。


    强类型意味着类型之间的转换存在限制。静态类型化意味着类型不是动态的——一旦变量被创建,就不能更改它的类型。


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

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

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

    请注意,当我使用"可能"这个词时,这是因为这些术语没有公认的定义。从目前的答案中你已经看到了。


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

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


    Answer is already given above. Trying to differentiate between strong vs week and static vs dynamic concept.

    强类型与弱类型是什么?

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

    在Go或类似于Python的强类型语言中,"2"+8将引发类型错误,因为它们不允许"类型强制"。

    弱(松散)类型:将自动转换为一种类型到另一种类型:像javascript或perl这样的弱类型语言不会抛出错误,在这种情况下,javascript将得到"28",Perl将得到10。

    Perl示例:

    1
    2
    3
    my $a ="2" + 8;
    print $a,"
    ";

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

    静态与动态类型是什么?

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

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

    这是什么意思?

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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并运行,您将收到编译失败消息。

    1
    2
    3
    4
    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是动态类型的,所以它只转换和类型检查它正在执行的代码。else块从不为foo(2)执行,因此"2"+8从未被查看过,对于foo(0)调用,它将尝试执行该块并失败。

    1
    2
    3
    4
    5
    6
    7
    def foo(a):
        if a > 0:
            print 'I am feeling lucky.'
        else:
            print"2" + 8
    foo(2)
    foo(0)

    您将看到以下输出

    1
    2
    3
    4
    5
    6
    7
    8
    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