什么是类型安全的?

时间:2008-11-04 02:27:48

标签: language-agnostic programming-languages computer-science terminology type-safety

“类型安全”是什么意思?

12 个答案:

答案 0 :(得分:222)

类型安全意味着编译器将在编译时验证类型,如果您尝试将错误的类型分配给变量,则会抛出错误。

一些简单的例子:

// Fails, Trying to put an integer in a string
String one = 1;
// Also fails.
int foo = "bar";

这也适用于方法参数,因为您将显式类型传递给它们:

int AddTwoNumbers(int a, int b)
{
    return a + b;
}

如果我尝试使用以下方式调用它:

int Sum = AddTwoNumbers(5, "5");

编译器会抛出一个错误,因为我传递一个字符串(“5”),并且它期望一个整数。

在松散类型的语言中,例如javascript,我可以执行以下操作:

function AddTwoNumbers(a, b)
{
    return a + b;
}

如果我这样称呼它:

Sum = AddTwoNumbers(5, "5");

Javascript自动将5转换为字符串,并返回“55”。这是因为javascript使用+符号进行字符串连接。要使其具有类型感知功能,您需要执行以下操作:

function AddTwoNumbers(a, b)
{
    return Number(a) + Number(b);
}

或者,可能:

function AddOnlyTwoNumbers(a, b)
{
    if (isNaN(a) || isNaN(b))
        return false;
    return Number(a) + Number(b);
}

如果我这样称呼它:

Sum = AddTwoNumbers(5, " dogs");

Javascript会自动将5转换为字符串,并附加它们,以返回“5只狗”。

并非所有动态语言都像javascript一样宽容(事实上,动态语言并不暗示一种松散的类型语言(参见Python)),其中一些实际上会在无效类型转换时给你一个运行时错误。

虽然方便,但它可以让您轻松错过许多错误,并且只能通过测试正在运行的程序来识别。就个人而言,我更愿意让我的编译器告诉我是否犯了这个错误。

现在,回到C#...

C#支持名为covariance的语言功能,这基本上意味着您可以将基类型替换为子类型而不会导致错误,例如:

 public class Foo : Bar
 {
 }

在这里,我创建了一个新的类(Foo),它是Bar的子类。我现在可以创建一个方法:

 void DoSomething(Bar myBar)

并使用Foo或Bar作为参数调用它们,两者都可以正常工作而不会导致错误。这是有效的,因为C#知道Bar的任何子类都将实现Bar的接口。

然而,你不能做反过来:

void DoSomething(Foo myFoo)

在这种情况下,我无法将Bar传递给此方法,因为编译器不知道Bar实现了Foo的接口。这是因为子类可以(通常会)与父类有很大不同。

当然,现在我已经远离了原始问题的范围,超出了原始问题的范围,但是要知道它的所有好东西:)

答案 1 :(得分:44)

不应将类型安全与静态/动态类型或强/弱类型相混淆。

类型安全语言是指人们可以对数据执行的唯一操作是由数据类型进行宽容的语言。也就是说,如果您的数据类型为XX不支持操作y,则该语言将不允许您执行y(X)

当选中时,此定义不会在上设置规则。它可以在编译时(静态类型)或在运行时(动态类型),通常是通过异常。它可以是两者兼而有之:一些静态类型语言允许您将数据从一种类型转换为另一种类型,并且必须在运行时检查强制转换的有效性(假设您正在尝试将Object强制转换为Consumer - 编译器无法知道它是否可接受。)

类型安全并不一定意味着强类型 - 某些语言是出了名的弱类型,但仍然可以说是类型安全的。以Javascript为例:它的类型系统虽然很弱,但仍然严格定义。它允许自动转换数据(例如,字符串到整数),但是在明确定义的规则中。据我所知,Javascript程序不会以未定义的方式运行,如果你足够聪明(我不是),你应该能够预测在阅读Javascript代码时会发生什么。

类型不安全的编程语言的一个例子是C:读取/写入数组边界之外的数组值具有未定义的行为 by specification 。无法预测会发生什么。 C是一种具有类型系统的语言,但不是类型安全的。

答案 2 :(得分:26)

这里的许多答案都将类型安全与静态类型和动态类型混为一谈。动态类型语言(如smalltalk)也可以是类型安全的。

简短回答:如果没有操作导致未定义的行为,则语言被认为是类型安全的。许多人认为语言严格类型所需的显式类型转换的要求,因为自动转换有时会导致明确定义但意外/不直观的行为。

答案 3 :(得分:20)

类型安全不仅仅是编译时约束,而是运行时约束。我觉得即便这样,我们可以进一步明确这一点。

有两个与类型安全相关的主要问题。内存**和数据类型(及其相应的操作)。

内存**

char通常每个字符需要1个字节,或8位(取决于语言,Java和C#存储需要16位的unicode字符)。 int需要4个字节,或32位(通常)。

目视:

char: |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型安全语言不允许在运行时中将int插入到char中(这应该抛出某种类型的转换或内存不足异常)。但是,在类型不安全的语言中,您将覆盖另外3个相邻字节的内存中的现有数据。

int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

在上面的例子中,右边的3个字节被覆盖,因此任何指向该内存的指针(比如3个连续的字符)都会产生垃圾。这会导致程序中出现undefined行为(或者更糟糕的是,可能在其他程序中,这取决于操作系统如何分配内存 - 这些日子不太可能)。

** 虽然第一个问题在技术上并不是关于数据类型的,但是类型安全语言本身就能解决这个问题,并且它可以直观地向那些不知道内存分配"看起来如何"。

数据类型

更精细和直接的类型问题是两种数据类型使用相同的内存分配。取一个int与一个unsigned int。两者都是32位。 (就像char [4]和int一样容易,但更常见的问题是uint与int)。

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型不安全语言允许程序员引用正确分配的32位跨度,但是当unsigned int的值被读入int的空间(反之亦然)时,我们再次undefined行为。想象一下这可能会导致银行业计划出现的问题:

  

"多德!我花了30美元,现在剩下65,506美元!"

...'当然,银行业务程序使用更大的数据类型。 ;)哈哈!

正如其他人已经指出的那样,下一个问题是对类型的计算操作。这已经被充分涵盖了。

速度与安全

今天大多数程序员从不需要担心这些事情,除非他们使用像C或C ++这样的东西。这两种语言都允许程序员在运行时轻松违反类型安全性(直接内存引用),尽管编译器“尽最大努力降低风险。但是,这并非全是坏事。

这些语言计算速度快的一个原因是它们不会在运行时操作(例如Java)中验证类型兼容性。他们认为开发人员是一个很好的理性人,他们不会在一起添加字符串和int,为此,开发人员可以获得速度/效率。

答案 4 :(得分:9)

“类型安全”的编程语言意味着以下内容:

  1. 您无法读取未初始化的变量
  2. 您不能将数组索引超出其范围
  3. 您无法执行未经检查的类型转换

答案 5 :(得分:8)

来自文科专业的解释,而非科学专业:

当人们说语言或语言特征是类型安全的时,它们意味着该语言将帮助阻止您,例如,将非整数的东西传递给某些需要整数的逻辑。

例如,在C#中,我将函数定义为:

 void foo(int arg)

编译器将阻止我这样做:

  // call foo
  foo("hello world")

在其他语言中,编译器不会阻止我(或者没有编译器...),因此字符串将被传递给逻辑,然后可能发生坏事。

类型安全语言尝试在“编译时”捕获更多内容。

另一方面,对于类型安全的语言,当你有一个类似“123”的字符串并且你想像int一样对它进行操作时,你必须编写更多代码来将字符串转换为int,或者当你有一个类似于123的int,并希望在消息中使用它,例如“答案是123”,你必须编写更多代码来将其转换/转换为字符串。

答案 6 :(得分:4)

类型安全意味着以编程方式,变量,返回值或参数的数据类型必须符合特定条件。

实际上,这意味着7(整数类型)与“7”(字符串类型的引用字符)不同。

PHP,Javascript和其他动态脚本语言通常是弱类型的,因为如果你试图添加“7”+ 3,它们会将(字符串)“7”转换为(整数)7,尽管有时你有明确地执行此操作(并且Javascript使用“+”字符进行连接)。

C / C ++ / Java不会理解,或者将结果连接成“73”。类型安全通过明确类型要求来防止代码中的这些类型的错误。

类型安全非常有用。上述“7”+ 3的解决方案是输入cast(int)“7”+ 3(等于10)。

答案 7 :(得分:4)

为了更好地理解,请观看下面的视频,该视频演示了安全语言(C#)和非安全语言(javascript)中的代码。

http://www.youtube.com/watch?v=Rlw_njQhkxw

现在是长篇文章。

类型安全意味着防止类型错误。当一种类型的数据类型被分配给其他类型UNKNOWINGLY并且我们得到不合需要的结果时会发生类型错误。

例如,JavaScript不是一种类型安全的语言。在下面的代码中,“num”是一个数字变量,“str”是字符串。 Javascript允许我做“num + str”,现在GUESS会做算术或连接。

现在对于下面的代码,结果是“55”,但重要的是混乱创造了它将要做什么样的操作。

这种情况正在发生,因为javascript不是一种类型安全的语言。它允许将一种类型的数据设置为另一种类型而没有限制。

<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays  “55”
</script>

C#是一种类型安全的语言。它不允许将一种数据类型分配给其他数据类型。以下代码不允许在不同的数据类型上使用“+”运算符。

enter image description here

答案 8 :(得分:2)

试试......

TypeSafe表示在编译时静态检查变量以进行适当的赋值。例如,consder是字符串或整数。这两种不同的数据类型不能交叉分配(即,您不能将整数分配给字符串,也不能将字符串分配给整数)。

对于非类型安全行为,请考虑以下事项:

object x = 89;
int y;

如果您尝试这样做:

y = x;

编译器抛出一个错误,指出它无法将System.Object转换为Integer。你需要明确地这样做。一种方法是:

y = Convert.ToInt32( x );

上面的分配不是类型安全的。类型安全分配是可以直接将类型分配给彼此的类型。

ASP.NET中存在大量非类型安全集合(例如,应用程序,会话和视图状态集合)。关于这些集合的好消息是(最小化多个服务器状态管理注意事项),您可以在三个集合中的任何一个中放置几乎任何数据类型。坏消息:因为这些集合不是类型安全的,所以当你取回它们时,你需要适当地转换它们。

例如:

Session[ "x" ] = 34;

工作正常。但要重新分配整数值,您需要:

int i = Convert.ToInt32( Session[ "x" ] );

了解有关设施可帮助您轻松实现类型安全集合的方法的泛型。

C#是一种类型安全的语言,但要注意有关C#4.0的文章;有趣的动态可能性迫在眉睫(C#实质上是选择严格的一件好事:关闭......我们会看到。)

答案 9 :(得分:2)

Type-Safe是仅访问其有权访问的内存位置的代码,并且只能以明确定义的允许方式访问。 类型安全代码无法对对该对象无效的对象执行操作。 C#和VB.NET语言编译器总是生成类型安全的代码,在JIT编译期间验证它是类型安全的。

答案 10 :(得分:1)

类型安全意味着可以分配给程序变量的值集必须符合定义明确且可测试的标准。类型安全变量导致更强大的程序,因为操纵变量的算法可以信任变量只接受一组定义明确的值。保持这种信任可确保数据和程序的完整性和质量。

对于许多变量,可以分配给变量的值集在程序写入时定义。例如,可以允许称为“颜色”的变量采用值“红色”,“绿色”或“蓝色”,而不允许任何其他值。对于其他变量,这些标准可能会在运行时更改。例如,一个名为“color”的变量可能只允许在关系数据库的“Colors”表的“name”列中取值,其中“red”,“green”和“blue”是三个值对于“颜色”表中的“名称”,但计算机程序的某些其他部分可能能够在程序运行时添加到该列表,并且该变量在添加到“颜色”表后可以采用新值。

许多类型安全语言通过坚持严格定义变量类型并仅允许为变量赋予相同“类型”的值来给出“类型安全”的错觉。这种方法存在一些问题。例如,一个程序可能有一个变量“yearOfBirth”,这是一个人出生的年份,并且很容易将其类型转换为一个短整数。但是,它不是一个短整数。今年,这个数字小于2009年,大于-10000。但是,随着程序的运行,这一组每年增长1。将其作为“短线”是不够的。使此变量类型安全所需的是运行时验证函数,该函数确保数字始终大于-10000且小于下一个日历年。没有编译器可以强制执行此类条件,因为这些条件始终是问题域的唯一特征。

使用动态类型(或鸭子类型或清单类型)的语言(如Perl,Python,Ruby,SQLite和Lua)没有类型变量的概念。这迫使程序员为每个变量编写运行时验证例程,以确保它是正确的,或者承受不明原因的运行时异常的后果。根据我的经验,使用静态类型语言(如C,C ++,Java和C#)的程序员经常会认为静态定义的类型是他们为了获得类型安全的好处所需要的。对于许多有用的计算机程序来说,这根本不是真的,并且很难预测它是否适用于任何特定的计算机程序。

长&amp;短......你想要类型安全吗?如果是,则编写运行时函数以确保在为变量赋值时,它符合明确定义的条件。缺点是它使大多数计算机程序的域分析变得非常困难,因为你必须明确定义每个程序变量的标准。

答案 11 :(得分:0)

概念:

为简单起见,如含义的类型安全,它确保变量的类型应像

这样安全。
  1. 没有错误的数据类型,例如无法保存或初始化带有整数的字符串类型的变量
  2. 无法访问超出范围的索引
  3. 仅允许特定的存储位置

因此,这与变量的存储类型有关。