“类型安全”是什么意思?
类型安全意味着编译器将在编译时验证类型,如果试图将错误的类型赋值给变量,则抛出错误。
一些简单的例子:
// 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#支持一种叫做协方差的语言特性,这基本上意味着你可以用基类型替换子类型,而不会导致错误,例如:
public class Foo : Bar
{
}
在这里,我创建了一个新类(Foo),它是Bar的子类。我现在可以创建一个方法:
void DoSomething(Bar myBar)
并使用Foo或Bar作为参数调用它,两者都不会引起错误。这是因为c#知道Bar的任何子类都将实现Bar的接口。
然而,你不能做相反的事情:
void DoSomething(Foo myFoo)
在这种情况下,我不能将Bar传递给这个方法,因为编译器不知道Bar实现了Foo的接口。这是因为子类可以(而且通常会)与父类有很大不同。
当然,现在我已经走得太远了,超出了最初问题的范围,但知道这些都是好事:)
来自文科专业而不是计算机科学专业的解释:
当人们说一种语言或语言特性是类型安全的时,他们的意思是该语言将有助于防止,例如,将非整数的东西传递给某个期望整数的逻辑。
例如,在c#中,我将一个函数定义为:
void foo(int arg)
编译器会阻止我这样做:
// call foo
foo("hello world")
在其他语言中,编译器不会阻止我(或者没有编译器…),所以字符串将被传递给逻辑,然后可能会发生一些不好的事情。
类型安全语言试图在“编译时”捕获更多。
缺点是,使用类型安全语言,当你有一个像“123”这样的字符串,你想像整型一样对它进行操作时,你必须写更多的代码来将字符串转换为整型,或者当你有一个像123这样的整型,并且想在一个像“答案是123”这样的消息中使用它时,你必须写更多的代码来将它转换/强制转换为字符串。
试试这个解释……
TypeSafe意味着在编译时静态检查变量是否有适当的赋值。例如,考虑一个字符串或整数。这两种不同的数据类型不能交叉赋值(也就是说,不能将整数赋值给字符串,也不能将字符串赋值给整数)。
对于非类型安全的行为,考虑如下:
object x = 89;
int y;
如果你试图这样做:
y = x;
编译器抛出一个错误,表示它不能转换一个系统。对象转换为整数。你需要明确地这样做。一种方法是:
y = Convert.ToInt32( x );
上面的赋值不是类型安全的。类型安全赋值是指类型可以直接相互赋值。
非类型安全的集合在ASP。NET(例如,应用程序、会话和视图状态集合)。关于这些集合的好消息是(尽量减少多个服务器状态管理方面的考虑),您可以在这三个集合中的任何一个中放入几乎任何数据类型。坏消息是:因为这些集合不是类型安全的,所以在取回值时需要适当地强制转换。
例如:
Session[ "x" ] = 34;
工作很好。但是要将整数值赋回,你需要:
int i = Convert.ToInt32( Session[ "x" ] );
阅读泛型,了解该工具帮助您轻松实现类型安全集合的方式。
c#是一种类型安全语言,但请关注有关c# 4.0的文章;有趣的动态可能性正在逼近(c#实际上得到了严格的选项:关闭,这是一件好事吗?我们将会看到)。
类型安全意味着在编程上,变量、返回值或参数的数据类型必须符合特定的标准。
实际上,这意味着7(整数类型)不同于"7"(字符串类型的引号字符)。
PHP, Javascript和其他动态脚本语言通常是弱类型的,因为它们将转换(字符串)如果您尝试将“7”+ 3添加为“7”到(整数)7,尽管有时您必须显式地这样做(Javascript使用“+”字符进行连接)。
C/ c++ /Java不会理解,或者会将结果连接到“73”中。类型安全通过明确类型需求来防止代码中出现这些类型的错误。
类型安全非常有用。上述“7”+ 3的解决方案是类型转换(int)7 + 3(等于10)。
类型安全意味着可以分配给程序变量的值集必须符合定义良好且可测试的标准。类型安全变量导致程序更加健壮,因为操作变量的算法可以相信变量只接受定义良好的一组值中的一个。保持这种信任可以确保数据和程序的完整性和质量。
For many variables, the set of values that may be assigned to a variable is defined at the time the program is written. For example, a variable called "colour" may be allowed to take on the values "red", "green", or "blue" and never any other values. For other variables those criteria may change at run-time. For example, a variable called "colour" may only be allowed to take on values in the "name" column of a "Colours" table in a relational database, where "red, "green", and "blue", are three values for "name" in the "Colours" table, but some other part of the computer program may be able to add to that list while the program is running, and the variable can take on the new values after they are added to the Colours table.
Many type-safe languages give the illusion of "type-safety" by insisting on strictly defining types for variables and only allowing a variable to be assigned values of the same "type". There are a couple of problems with this approach. For example, a program may have a variable "yearOfBirth" which is the year a person was born, and it is tempting to type-cast it as a short integer. However, it is not a short integer. This year, it is a number that is less than 2009 and greater than -10000. However, this set grows by 1 every year as the program runs. Making this a "short int" is not adequate. What is needed to make this variable type-safe is a run-time validation function that ensures that the number is always greater than -10000 and less than the next calendar year. There is no compiler that can enforce such criteria because these criteria are always unique characteristics of the problem domain.
Languages that use dynamic typing (or duck-typing, or manifest typing) such as Perl, Python, Ruby, SQLite, and Lua don't have the notion of typed variables. This forces the programmer to write a run-time validation routine for every variable to ensure that it is correct, or endure the consequences of unexplained run-time exceptions. In my experience, programmers in statically typed languages such as C, C++, Java, and C# are often lulled into thinking that statically defined types is all they need to do to get the benefits of type-safety. This is simply not true for many useful computer programs, and it is hard to predict if it is true for any particular computer program.
长和短....您需要类型安全吗?如果是,那么编写运行时函数来确保当变量被赋值时,它符合定义良好的标准。缺点是它使域分析对于大多数计算机程序来说非常困难,因为您必须显式地为每个程序变量定义标准。
这里的许多答案将类型安全与静态类型和动态类型混为一谈。动态类型语言(如smalltalk)也可以是类型安全的。
简单的回答是:如果没有操作导致未定义的行为,则该语言被认为是类型安全的。许多人认为显式类型转换的要求对于严格类型的语言是必要的,因为自动转换有时会导致定义良好但意想不到/不直观的行为。
类型安全的代码只访问它被授权访问的内存位置,并且只能以定义良好的、允许的方式访问。 类型安全代码不能在对象上执行对该对象无效的操作。c#和VB。NET语言编译器总是生成类型安全的代码,这些代码在JIT编译期间被验证为类型安全的。
为了更好地理解,请观看下面的视频,该视频演示了类型安全语言(c#)和非类型安全语言(javascript)的代码。
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#是一种类型安全语言。它不允许将一种数据类型分配给另一种数据类型。下面的代码不允许在不同的数据类型上使用“+”运算符。
类型安全不应与静态/动态类型或强/弱类型相混淆。
类型安全语言是这样一种语言,在这种语言中,只能对数据执行数据类型所允许的操作。也就是说,如果您的数据是X类型,而X不支持操作y,那么该语言将不允许您执行y(X)。
这个定义没有设置何时检查的规则。它可以在编译时(静态类型)或在运行时(动态类型),通常通过异常进行。它可以两者兼有:一些静态类型语言允许您将数据从一种类型转换为另一种类型,并且必须在运行时检查转换的有效性(假设您试图将对象转换为消费者—编译器无法知道它是否可接受)。
Type-safety does not necessarily mean strongly typed, either - some languages are notoriously weakly typed, but still arguably type safe. Take Javascript, for example: its type system is as weak as they come, but still strictly defined. It allows automatic casting of data (say, strings to ints), but within well defined rules. There is to my knowledge no case where a Javascript program will behave in an undefined fashion, and if you're clever enough (I'm not), you should be able to predict what will happen when reading Javascript code.
类型不安全编程语言的一个例子是C语言:在数组边界之外读取/写入数组值的规范没有定义行为。预测将会发生什么是不可能的。C是一种具有类型系统的语言,但不是类型安全的。
类型安全不仅是编译时约束,也是运行时约束。我觉得即使过了这么久,我们也可以进一步明确这一点。
与类型安全相关的主要问题有两个。内存**和数据类型(与其对应的操作)。
内存* *
一个字符通常需要每个字符1个字节,或者8位(取决于语言,Java和c#存储unicode字符需要16位)。 int需要4个字节,或32位(通常)。
视觉:
字符 : |-|-|-|-|-|-|-|-|
int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
类型安全语言不允许在运行时将int类型插入到char类型中(这会抛出某种类型的类强制转换或内存溢出异常)。但是,在一种类型不安全的语言中,您将覆盖现有数据的相邻内存多3个字节。
Int >> char:
|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|
在上面的例子中,右边的3个字节被覆盖,所以任何指向该内存的指针(比如3个连续的字符),希望得到一个可预测的char值现在都是垃圾。这将导致您的程序中出现未定义的行为(或者更糟,可能会在其他程序中出现,这取决于操作系统如何分配内存——目前不太可能)。
**虽然第一个问题在技术上不是关于数据类型的,但类型安全语言固有地解决了这个问题,并且它向那些不知道内存分配“看起来”如何的人直观地描述了这个问题。
数据类型
更微妙和直接的类型问题是两种数据类型使用相同的内存分配。取int型和unsigned int型。两者都是32位。(也可以是char[4]和int,但更常见的问题是uint vs. int)。
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|
类型不安全语言允许程序员引用正确分配的32位span,但当将无符号整型的值读入整型的空间时(反之亦然),我们再次遇到未定义的行为。想象一下这可能会给银行项目带来的问题:
“伙计!我透支了30美元,现在我还剩65,506美元!!”
...当然,银行程序使用更大的数据类型。,)哈哈!
正如其他人已经指出的,下一个问题是对类型的计算操作。这一点已经得到了充分的讨论。
速度vs安全
今天的大多数程序员都不需要担心这些事情,除非他们使用的是C或c++之类的东西。这两种语言都允许程序员在运行时轻易地违反类型安全(直接内存引用),尽管编译器尽最大努力将风险降至最低。然而,这也不全是坏事。
这些语言计算速度如此之快的一个原因是它们不需要像Java那样在运行时操作期间验证类型兼容性。他们认为开发人员是一个很理性的人,不会把字符串和int放在一起,因此,开发人员获得了速度/效率的奖励。
概念:
为了像含义一样非常简单的类型安全,它确保变量的类型应该是安全的
没有错误的数据类型,例如不能保存或初始化字符串类型的整数变量 不可访问超出绑定的索引 只允许特定的内存位置
所以这都是关于变量存储类型的安全性。
类型安全
在现代c++中,类型安全是非常重要的。类型安全意味着正确使用类型,因此避免不安全的类型强制转换和合并。c++中的每个对象都是根据其类型使用的,并且在使用之前需要对对象进行初始化。
安全初始化:{}
编译器在类型转换过程中防止信息丢失。例如, int {7};初始化没问题 \ . int b{7.5}编译器显示错误,因为信息丢失
不安全的初始化:=或()
编译器不会在类型转换期间防止信息丢失。 int a = 7初始化正常 int a = 7.5初始化正常,但信息丢失。a的实际值将变为7.0 int c(7)初始化OK int c(7.5)初始化是可以的,但是会发生信息丢失。a的实际值将变为7.0