栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

第二章 数据类型和变量

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

第二章 数据类型和变量

计算机诞生之初是为了科学数据的计算,编程语言则是让计算机按照我们的意愿来处理数据。这些处理的数据有很多种类,比如说数字,字符,图片,视频等等。编程语言为了更好的处理这些数据,将数据大致划分为数字类型和字符类型。不仅仅Java语言是这样划分的,其他编程语言也是这样划分的。

在Java语言中,数据类型分为基本数据类型和引用数据类型。关于引用数据类型,我们后在后面的章节中介绍。在基本数据类型中,可以分为数字型,字符型和布尔型。如下所述:

                                                                      |  整数类型:byte,short,int,long

                               |------数字类型-----------|

基本数据类型------|                                      |  小数类型:float,double

                               |------字符类型:char

                               |

                               |-------布尔类型:boolean

整数类型就不用说了,它代表的就是整数数据。为什么会有多个整数类型,其实它代表了不同大小的存储空间。数据类型不仅仅表示数据的格式,还表示其空间大小。

数据要处理,就必须在计算机中进行存储。这种存储包括两种方式,一种是以文件的形式硬盘上存储(例如我们编写的Java源程序),另一种是内存上存储,主要用于传递给CPU进行计算。编程语言中数据类型表示的空间大小,指的就是内存上的存储。我们可想而知,空间大的数据类型存储的整数范围也就越大。

那么整数类型byte(字节型),short(短整型),int(整型),long(长整型)所表示的存储空间大小是多少呢?

       byte 类型占据1 byte空间大小,能存储 -128到127之间的任何整数

       short类型占据2 byte空间大小,能存储 -32768到32767之间的任何整数

       int  类型占据 4 byte空间大小,大约能存储 -21亿到21亿之间的任何整数。

       long 类型占据8 byte空间大小,大约能存储- 922亿亿到922亿亿之间的任何整数。

我们可以看到,整数类型byte,short,int,long的存储空间依次倍数地增加,所存储的整数范围也越来越大,一般情况下,我们使用int就可以了。

这里我们要说的是byte数据类型,我们可以看到它既是一种数据类型,也是一种存储空间大小的单位。当它作为一种存储空间的单位的时候,称之为“字节”。

在编程语言中,字节(byte)就是最小的存储单位,所有的数据类型的大小都是它的整数倍。一个字节(byte)到底是多大呢?它其实代表了就是8个0或1,也就是类似于“01001010”这样的二进制数字,它就是一个字节(byte)。

既然字节(byte)是最小的存储单位,那么比它大的就是KB,MB,GB,TB等等,他们之间的转换关系都是1024倍,也就是说1KB=1024byte,1MB=1024KB,1GB=1024MB,1TB=1024GB。相信大家在日常生活中,也经常看到过这几种单位。通常一张被压缩过的图片的大小大于是100KB以内,一张高清的图片大约1-3MB左右。

在使用整数类型的时候,我们只需要记住它的大小范围即可。例如,我有一个数字65000,我能用short类型进行存储嘛?当然不行,因为这个数字超出了short类型的取值范围(-32768到32767),我们应该使用int来存储它。

接下来,我们继续讲解数字类型的另一种,就是小数类型,也称之为浮点类型,它有两种,一个是单精度float,另一个是双精度double,他们代表的存储空间如下:

       float 类型占据 4 byte空间大小,大约能够精确小数6位

       double 类型占据8 byte空间大小,大约能够精确小数15位

浮点数的取值范围与其精度取决于它的二进制存储,浮点数在内存中是按科学计数法来存储的,一个浮点数的存储分为三部分:符号位,指数位,尾数位。因为涉及内容比较繁琐,所以我们不再详细介绍。一般情况下,我们使用double类型就足够了,而且对于一般的编程,我们不需要高精度的计算,我们能够保留小数后2位就可以了。如果是需求要求的话,我们可以精确到需求指定的位数。这里还要提醒大家的是,对于浮点型数据的计算,在计算过程中可能会丢失精度,造成结果不对,原因在于计算机小数存储和计算机制导致的。为了能保持尽量高的精度,我们可以将小数扩大为整数后在计算,最后再缩小为小数的结果。另外,Java语言还提供了一个特殊的数据类型bigdecimal类处理更高精度的数学计算。大家知道即可,不需要详细了解和使用。关于浮点型的内容,我们暂时就介绍到这里。

接下来,我们介绍字符类型char,它占据2个字节的存储空间,和整数数据float空间相同。它能表示我们日常使用的一些字符符号,比如说英文字母,标点符号,中文汉字,甚至是数字。数字也可以当作一种符号来理解。

字符型数字和整数类型数字是两个不同的概念。整数类型有大小和取值范围,因为计算机本质上就是由0和1组成的二进制表示的。计算机中所有的数据,记住是所有的数据,他们的本质都是由0和1组成的二进制存储的。我们知道我们日常使用的整数都是使用十进制表示的,而十进制和二进制是可以按照固定的公式进行转换的。例如十进制的4就等于二进制的100,注意这里的100不是一百,而是壹零零。关于十进制和二进制的转换,我们这里也不再介绍了。也就是说,我们的整数类型其实可以天然的使用二进制来进行表示。例如上面提到的十进制的4,如果他是一个byte类型,那么它的二进制表示就是“00000100”。但是,一个字符类型的数据,比如大写字母A,它应该使用什么二进制表示呢?

这个时候,我们就需要约定使用哪个二进制数来表示大写字母A,比如说使用“01000001”。那么这个事,谁说了算呢?这个又涉及到计算机编程语言的发展历史了。我们知道计算机和编程语言都是美国人发明的,因此最初的字符型的二进制约定也是由他们决定的。因为英语只有26个字母,再加上一些标点和特殊符号,因此这些字符型并不是太多。所以,美国国家标准学会(ANSI)就制定了ASCII编码表,统一规定了常用符号用哪些二进制数来表示。例如我们使用二进制值 “01000001”代表大写字母 A,二进制不容易记忆,我们就将二进制转成十进制,就是整数65了。ASCII码是一种字符集,也是一种单字节的字符编码方案,主要用于处理英语。

以上就是ASCII码表,共计128个字符的十进制整数表示。这里我们需要记住的是字符0(不是整数0)使用数值48代表,字符A使用数值65代表,字符a使用数值97代表。在这里,大家一定要清楚的理解,当数字作为字符类型存储使用的时候,它使用约定的二进制来代表,当数字作为整数类型存储使用的时候,它使用的就是自己的二进制来表示。计算机如何根据数值来绘制对应的字符形状,那就是跟字体相关的绘制方便的内容了。

既然char类型的本质就是二进制数,那么我们是不是可以使用数字来表示字符呢?当然可以了。也就是说我们可以使用97来表示一个字符,当输出这个字符的时候,它就是a。因为所有的char类型都使用的正整数来表示,因此,char类型的取值范围是0-65535。当然,这个数值范围并不是任何一个数字就代表一个字符。关于这一点,大家只需要知道char类型的本质是二进制数,我们使用整数值也可以表示对应的字符。

关于字符型数据类型,我们还有讲一下中文汉字。每一个中文汉字也需要约定好使用那个二进制来表示。需要注意的是,ASCII码表中一共才128个字符,使用1个byte大小就足够了。但是,我们中文汉字太多了,一个byte是不够的,至少使用两个byte才可以表示过来。当然,这个事情,就需要我们国家来制定了。我们常见的中文编码包括GB2312和GBK两种。GB2312是简体中文的编码,GBK是对它的进一步扩展,毕竟中文汉字太多,还涉及到繁体字。我们目前使用的中文版的Win7和Win10操作系统,默认就是使用GBK的中文编码。

为了满足世界各个国家的语言需求,国际标准化组织(ISO)为世界各种语言进行统一编码,也就是Unicode字符集。Unicode字符集只规定了文字符号的二进制数,却没有规定这个二进制数应该如何存储和传输。UTF8、UTF16和UFT32则是基于Unicode字符集的三种编码方式的实现。UTF8 是在互联网上使用最广的一种 Unicode 的编码实现方式。UTF8 是一种变长的编码方式,它使用1~4个字节表示一个符号。UTF16比起UTF8,好处在于大部分字符都以固定长度的双字节储存,也就是说UTF16更接近Unicode字符集。

字符集(Charset)和字符编码(Character Encoding)对我们编程来说,非常的重要。所有的数据都需要被存储,就必须涉及数据的编码和解码。如果你使用的是UTF8编码的数据,就必须使用UTF8来进行解码,否则就可能出现乱码。但是,基本上所有的编码方式都会兼容ASCII码。所以,在我们日常编程过程中,出现乱码的数据基本上都是中文汉字。除了编程过程中对数据的编码处理之外,我们的源程序文件同样也需要编码保存。现在大部分的编程工具都推荐使用UTF8编码方式,我们基本上也遵从这个规则。我们在Notepad++编辑器中的“格式(M)”的菜单栏中,可以看到当前源程序文件的编码格式。如果在Dos黑窗口中编程出现“错误:编码GBK 的不可映射字符”,那么我们可以将编码改成“以ANSI格式编码”,它的意思就是使用本机操作系统默认的编码格式,也就是GBK编码格式。

几种编码格式的比较:

对于中文字符来讲,GB2312和GBK编码规则类似,但是GBK表示汉字范围更大,所以选择GBK更加合适一些。UTF-6和UTF-8都是处理Unicode编码,它们的编码规则不太相同。相比较而言,UTF-16编码效率最高,字符到字节相互转换更简单,进行字符串操作也更好。所以Java的内存编码就是采用UTF-16编码。但是它不适合在网络之间传输,因为网络传输容易损坏字节流,因此UTF-8更适合网络传输,对于ASCII字符采用单字节存储,在编码效率上介于GBK和UTF-16之间。所以UTF-8在编码效率和安全性做了平衡,优先选择使用。

最后我们要说的就是布尔类型boolean,这个类型非常的简单,它占据1个byte的空间大小。但是它只有两个值,一个是true,表示真,另一个是false,表示假。虽然布尔类型非常的简单,但是它在编程过程中使用非常的频繁,后期我们在开发过程中就自然明白了。

Java的基本数据类型讲完之后,就是第二个内容:变量。我们上面也提到过,数据需要存储到内存中才能进一步的处理,数据类型代表了数据的格式和空间大小,它并不能代表数据在内存中那个位置被存储。这里要讲的变量,其本质就是内存地址(但它还不完全是)。也就是说,数据类型要和变量一起搭配使用,才能将数据存储到内存中。

例如,我们现在有一个数据100,我们要想把它方到内存中去的话,就需要这样:int a = 100;

因为100是一个整数,因此我们使用整型int,然后a就是变量,=是赋值操作符,100是一个字面常量(字面值),也就是我们的数据100,分号代表Java程序语句的结束。这句Java程序语句(代码),表示的含义就是把数据100放到变量a代表的内存空间中,这个内存空间是4 byte的大小,并且该空间中只能放置整数类型的数字。

这个过程,我们称之为变量的声明或定义。变量必须先定义再使用,而且定义是一次性的,不能也不需要重复定义。变量定义的时候,可以对变量直接赋值,我们称之为初始化。当然,我们也可以不对变量赋值,这样变量代表的内存空间则是空的,大部分情况下,我们还是建议进行变量初始化。

有人可能想问,这个变量对应的内存空间到底在哪里呢?其实我们也没必要太过于纠结这个问题。因为内存的管理和分配都是由操作系统来决定的,内存的空间很大,操作系统会按照一定的规则分配内存地址编号,类似于酒店的房间编号。当操作系统给变量a分配内存地址编号之后,我们就可以向变量a中放置整型数据了。当然,我们也可以通过一些手段来查看变量a背后的内存地址编号,这里我们就不再详细介绍了。

变量不仅仅表示内存地址编号,我们对数据的读写都是通过变量来完成的。当我们将100赋值给变量a的时候,这就是写的操作,当然这需要赋值操作符=。后面的话,我们就可以直接使用变量a来访问里面的数据100了。例如,我们将变量里面的数据输出:

System.out.println(a);

变量的本质是内存的存储空间,在这个存款空间里面可以随时改变里面存储的数据。就这好比酒店的房间里面的房客,今天可能是张三住,明天可能是李四住。改变变量的数值,其实就是写操作,可以直接使用:a = 200;

注意,在修改变量的时候,就不需要数据类型int了。数据类型和变量一起使用的时候,是变量的定义,定义只允许出现一次即可。当改变了变量a的值后,再次访问的时候,它就是200了。变量就是一个可变的量。我们可以总结一下完整的代码,如下:

public class Hello {
	
	public static void main(String[] arg){
		
		
		int a = 100;
		System.out.println(a);
		
		a = 200;
		System.out.println(a);
		
		System.out.println("hello world!");
	}
}

 上面的代码中,我们基本上都是一行一句代码,每一行代码以分号结束。这样写,只是让代码更加清晰,属于代码规范的部分,不属于Java语法。我们再次强调一下,不符合Java语法的是无法通过编译的,而代码规范可以不遵守。但是,我们最好还是要遵守的,否则我们讲所有代码都堆砌成一起,密密麻麻的,我们自己都无法阅读和理解的。

还记得如何编译和运行Java程序吗?我们进入到源程序保存目录E:workspace下,然后在目录地址栏中输入:cmd后回车,进入Dos黑窗口中,然后输入编译命令:javac Hello.java,编译完毕后输入运行命令:java Hello

 接下来,我们来讲一下变量的命名规则,大家不要以为a就是固定的变量,其实它只是一个名字而已,我们完全可以使用其他名字,例如:int b = 100;

那么,这里必须涉及到变量名称的规则:可以使用任意的大小写字母,数字,下划线(_)和美元符号($)组成,但是不能以数字开头,不能使用Java中的关键字。

在Java语言中,凡是可以由我们程序人员定义的名称,都称之为“标识符”。所有标识符的命名规则都要遵从上面的规则。一般情况下,我们使用字母即可,这样方便大家理解。Java中关键字是什么?关键字是编程语言里事先定义好并赋予特殊含义的单词,也称保留字。例如我们上面提到的数据类型btye,short,int,long,float,double,char,boolean都属于关键字,我们不能使用他们作为变量的名称。Java的关键字还有很多,大家在后续的编程学习中会一点一点的掌握,现在没有必要刻意的去记录下来。

记住,如果不按照上面的规则定义变量的名称,源程序是不能编译成功的,它会报错。例如,我们将int a=100; 改为 int 8=100; 当我们再次编译:javac Hello.java的时候,就会报错。因为数字是不可以单独作为变量的名称的。这是Java的语法规则,我们必须遵守。

我们说,变量是一个可以改变的量,那么是否存在不可改变的量呢?当然存在,它就是常量。常量广义上可以分为字面常量(字面值)和符号常量(固定的变量)。再上文中int a=100;的代码中,这个数字100其实就是字面常量,也称为为字面值。而符号常量的定义如下:

final int w = 100; 它其实就是在普通变量定义的基础上增加了关键字final而已。但是,经过final修饰过的变量就会变成一个常量,这个常量w在后面使用过程中,不允许修改它的值了,也就是说,它永远只能是100了。关于符号常量我们不再介绍。

我们继续回到字面值上面来。它就是我们要处理的数据,是数据自然会有数据类型之分。默认情况下,整数字面值都属于int类型,小数字面值都属于double类型,字符字面值也就属于char类型了。

public class Hello {
	
	public static void main(String[] arg){
		
		
		int a = 100;
		System.out.println(a);
		
		a = 200;
		System.out.println(a);
		
		double b = 0.1;
		System.out.println(b);
		
		char c = 'a';
		System.out.println(c);
		
		char d = 97;
		System.out.println(d);
		
		boolean e = true;
		System.out.println(e);
		
		System.out.println("hello world!");
	}
}

 运行结果我们不在给出,大家可以自己运行。我们在上述代码中,分别定义了四种数据类型,一个整型,一个浮点型,两个字符型和一个布尔型。请注意,字符型字面值需要使用单引号包裹起来,也可以使用对应的ASCII整数表示。在上面的变量赋值操作中,隐含了一个条件,就是整型的字面值必须赋值给整型int的变量,浮点型的字面值必须赋值给浮点型double的变量,字符的字面值必须赋值给字符型char的变量。如果两者不一致的话,可能编译错误,甚至还会涉及到数据类型转换问题。现阶段我们不需要过多的理解数据类型转换的内容,因为这样反而会让大家更加的迷惑。

我们只需要了解和掌握的是,在对byte,short,int,long进行赋值的时候,这个字面值不可以超过对应数据类型的取值范围。比如byte不能赋值超过127,short不能超过32767,int不能超过2147483647,long不能超过9223372036854775807。如果超过,编译报错!

这里比较特殊的是long类型,一般情况下,我们会使用大写字母L来做后缀定义长整型的字面值。例如:long x = 5000000000L; 我们上面说过,一个整数的字面值默认是int类型,这里我们使用的5000000000字面值默认也是int类型,但它很明显超过了int类型的最大值,这样的代码是无法通过编译的。因此我们在5000000000的后面添加一个L将其定义为一个long类型,这样long类型的字面值就可以顺利的赋值给long类型的变量了。

当然了,如果数字没有超过int类型的范围,我们也不需要添加字母L这个后缀了。

例如: long x = 100; 就没有任何问题了。但是,这又涉及到另一个问题,100默认是int类型,将一个int类型赋值给long类型的话,会进行数据类型的转换。因为int类型是4个字节(byte),long类型是8个字节(byte),它是一个低精度(小空间)向高精度(大空间)的转换过程,数据精度不会丢失,因此Java语言默默的将这个转换自动处理了,不需要我们程序员参与。这种情况,我们称之为自动类型转换,或者叫隐式数据类型转换,该情况还包括byte赋值short,short赋值int,float赋值double等等。

但是如果一个高精度(大空间)的数据类型向低精度(小空间)数据类型进行转换呢?很显然,这个可能会造成精度丢失,设置数据错误的发生。例如,short m = 500; byte n = m;

这就不行了,Java语法不允许这样做,编译的时候会报错。因为我们不可以将500赋值给byte,byte最大存储才127,它无法存储500这个数值的。

但是,如果是这样呢:short m = 100; byte n = m;

因为Java语法不允许这样做,但是从实际情况来看,100这个数值是可以赋值给byte类型的,我们可以通过强制类型转换:byte n = (byte)m;

也就是在变量m的前面添加括号,里面填写byte,这样代码就可以顺利编译且运行了。当然,这个强制类型转换不可以随便使用的,它的前提是你转换后的数值的实际精度不会丢失。如果你将m=500的进行强制转换给byte n的话,虽然代码可以编译成功,但是最后变量n的值不是500啊,这样的强制转换不就错了嘛!

上面的数据类型转换只介绍了整型内部之间的转换,其实浮点型内部之间的转换也存在上述问题。也就是说float可以向double进行隐式转换,而double到float则只能强制转换。那么整型和浮点型的转换呢?一般情况下,整型可以向浮点型转换,因为精度不会丢失;而浮点型向整型转换的话,则需要进行强制转换,如果存在有效小数位的话,精度一定丢失。

最后在讨论一下字符char与整型(short)的转换。因为char本质上就是使用整型来存储的,因此两者可以相互转换的。比如上文代码中的字符a和97就是一个例子。甚至,我们完全可以将char当作short来使用,比如进行数学计算。两者的区别在于,char来输出的时候,按照对应的字符形式输出,当然我们也可以强制类型转换让其输出数值。

这里需要注意的是,字符型的数字和其存储的整型数值不是一一对应的,我们通过ASCII码可以看到,字符‘0’对应的存储数值是48,也就是说,我们把字符‘0’转换为整型后是48。那么,我们如何将字符‘0’转换为数值0呢?

很简单,使用差运算即可:char a = '4';  int x = a - '0';

今天的内容就讲的这里,我们来总结一下。今天我们主要讲了Java的数据类型和变量,两者搭配使用就可以存储数据了。数据类型分为byte,short,int,long,float,double,boolean共计7种。对于整数类型(byte,shot,int,long),我们需要记住它的取值范围。对于浮点型(float,double)我们记住它的有效精度即可。一般情况下,我们常用int和double就可以了。然后就是布尔类型boolean,它就两个值,一个是ture(真),一个是假(false)。最后就是数据类型转换,一般可以分为自动类型转换(隐式类型转换)和强制类型转换。自动类型转换是由Java来完成的,一般适用于低精度向高精度的转换。而强制类型转换则适用于高精度到低精度的转换,但是前提是数值的实际精度不能丢失,否者数据都错了,那就不可能得到正确的结果了。好的,谢谢大家的收看,欢迎大家在下方留言,我也会及时回复大家的留言的。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/971891.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号