"类型安全"是什么意思?
"类型安全"是什么意思?
类型安全意味着编译器将在编译期间验证类型,如果您尝试将错误类型分配给变量,则会抛出错误。
一些简单的例子:
// 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转换为字符串"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 dogs"。
并非所有的动态语言都像javascript一样宽容(实际上一个动态语言不隐含松散类型语言(参见Python)),有些语言在类型转换无效时会给出运行时错误。
虽然这很方便,但也容易出现错误,只能通过测试运行程序才能识别。个人而言,我更喜欢让编译器告诉我是否犯了这种错误。
现在,回到C#...
C#支持一种语言特性叫做 协变性,这基本上意味着你可以用子类型替换基类型而不会引发错误,例如:
public class Foo : Bar
{
}
在这里,我创建了一个新类(Foo),它是 Bar 的子类。现在我可以创建一个方法:
void DoSomething(Bar myBar)
你可以使用Foo或者Bar作为参数调用它,两者都能正常工作而不会引发错误。这是因为C#知道Bar的任何子类都将实现Bar接口。
然而,你不能做相反的操作:
void DoSomething(Foo myFoo)
在这种情况下,我无法将Bar传递给此方法,因为编译器不知道Bar实现了Foo的接口。这是因为子类可以(并且通常会)与父类非常不同。
当然,现在我已经走得太远,超出了原始问题的范围,但这些都是要了解的好东西 :)
类型安全不应与静态/动态类型或强/弱类型混淆。
一个类型安全的语言是指只有符合数据类型规范的操作才能对数据进行执行。也就是说,如果您的数据属于类型X
,并且X
不支持操作y
,那么该语言将不允许您执行y(X)
。
这个定义并没有规定检查时间。它可以在编译时(静态类型)或运行时(动态类型)进行检查,通常通过异常来实现。它也可能是两者结合:某些静态类型语言允许您将数据从一种类型转换为另一种类型,并且必须在运行时检查类型转换的有效性(假设您正在尝试将Object
转换为Consumer
- 编译器无法知道它是否可接受)。
类型安全并不一定意味着强类型语言,一些语言被公认为是弱类型语言,但仍然可以被认为是类型安全的。例如JavaScript:它的类型系统非常弱,但仍然是严格定义的。它允许自动转换数据(比如将字符串转换为整数),但必须遵循明确定义的规则。我所知道的没有一个JavaScript程序会表现出未定义的行为,如果您够聪明(我不是),那么在阅读JavaScript代码时应该能够预测会发生什么。
类型不安全的编程语言的一个例子是C:在数组边界之外读取/写入数组值的行为在规范中是未定义的。无法预测会发生什么。C是一种具有类型系统但不安全的语言。
类型安全不仅是编译时的约束,也是运行时的约束。即使经过这么长时间,我觉得我们仍然可以进一步阐明。
与类型安全相关的有两个主要问题。内存**和数据类型(以及其对应的操作)。
char
通常需要每个字符1字节,或8位(取决于语言,Java和C#存储Unicode字符需要16位)。
int
需要4个字节,或32位(通常)。
视觉上:
char: |-|-|-|-|-|-|-|-|
int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
类型安全语言不允许在运行时将int插入到char中(这应该会引发某种类别转换或内存不足异常)。但在类型不安全的语言中,你会覆盖3个相邻字节的现有数据。
int >> char:
|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|
在上述情况下,右侧的3个字节将被覆盖,因此任何指向该内存的指针(例如3个连续的char)预期获得可预测的char值,现在都变成了垃圾。这会导致程序中出现undefined
行为(或更糟糕的是,在其他程序中可能会出现问题,具体取决于操作系统如何分配内存-这在当今时代非常不可能发生)。
** 虽然第一个问题技术上与数据类型无关,但类型安全语言本质上解决了它,并将其可视化地描述给那些不知道内存分配“外观”的人。
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
ç±»å�‹ä¸�安全的è¯è¨€å…�许程åº�员引用æ£ç¡®åˆ†é…�çš„32ä½�间隔,但当 unsigned int 的值被读入 int 空间(或å��之亦然)时,我们å†�次出ç�°äº†æœªå®šä¹‰çš„行为。想象一下,在银行程åº�ä¸è¿™å�¯èƒ½ä¼šå¼•èµ·ä»€ä¹ˆé—®é¢˜ï¼š“类型安全”的编程语言指以下几点:
一个文科专业人士的解释,而不是计算机科学专业人士:
当人们说某种语言或语言特性是类型安全的时候,他们指的是这种语言将帮助你防止,例如,将不是整数的东西传递给一些期望整数的逻辑。
例如,在C#中,我定义一个函数如下:
void foo(int arg)
// call foo
foo("hello world")
http://www.youtube.com/watch?v=Rlw_njQhkxw
现在是一段较长的文本。
类型安全意味着防止类型错误。当不知情地将一个数据类型分配给另一个数据类型时,会发生类型错误,从而得到不良结果。
例如,JavaScript 不是一种类型安全的语言。在下面的代码中,“num”是数字变量,“str”是字符串。JavaScript 允许我执行“num + str”,现在猜测它会进行算术运算还是连接操作。
现在对于下面的代码,结果是“55”,但重要的是所创建的混淆是什么样的操作它会执行。
这是因为 JavaScript 不是一种类型安全的语言。它允许设置一种类型的数据到其他类型而没有限制。
<script>
var num = 5; // numeric
var str = "5"; // string
var z = num + str; // arthimetic or concat ????
alert(z); // displays “55”
</script>
C#是一种类型安全的语言。它不允许将一个数据类型分配给其他数据类型。下面的代码不允许在不同的数据类型上使用“+”运算符。
概念:
Type Safe(类型安全)的含义非常简单,它确保变量的类型是安全的,比如:
因此,这一切都关乎变量储存的类型安全。
类型安全意味着变量、返回值或参数的数据类型必须符合特定的标准。
实际上,这意味着7(整型)和“7”(字符串类型中的引号字符)是不同的。
PHP、Javascript和其他动态脚本语言通常是弱类型的,在尝试将“7”+3相加时会将(字符串)“7”转换为(整数)7,尽管有时需要显式执行此操作(而Javascript使用“+”字符进行连接)。
C/C++/Java将无法理解它,或将结果串联成“73”。类型安全通过使类型要求明确来防止代码中出现此类错误。
类型安全非常有用。解决上述“7”+3的问题是将(int) “7”+3进行类型强制转换,结果为10。
请尝试理解以下内容...
TypeSafe 意味着在编译时对变量进行静态检查以适当地赋值。例如,考虑字符串或整数。这两种不同的数据类型不能相互赋值(即,您不能将整数分配给字符串,也不能将字符串分配给整数)。
对于非类型安全行为,请考虑以下内容:
object x = 89;
int y;
如果你尝试这样做:
y = x;
y = Convert.ToInt32( x );
Session[ "x" ] = 34;
代码可以正常工作。但要将整数值重新赋回,您需要执行以下操作:
int i = Convert.ToInt32( Session[ "x" ] );
阅读有关泛型的文章,这种工具可以帮助您轻松实现类型安全的集合。
C#是一种类型安全的语言,但请注意C# 4.0的文章;有趣的动态可能性正在出现(C#基本上获得了Option Strict:Off,这是一件好事吗...我们会看到)。