数据类型的概念

• 数据结构的角度看
− 数据类型就是一个值的集合以及在这些值上定义的一组操作的总称。每种数据类型的值的集合称为该数据类型的域。数据类型不但定义了域,还定义了域上的操作。数据类型可以看作是程序设计语言中已经实现的数据结构。
− 这意味着,数据类型=数据集+运算
• 从计算机系统的角度看
− 编程语言的类型系统描述了其数据元素(常量和变量)与实际物理存储是如何联系的。
• 数据类型的出现源于以下三方面因素:
− 事物本身的不同。数据表示的概念或物质本身就有不同的类型,有的表示数值、有的表示字母、符号、声音或图像等。
− 计算机硬件的限制。一方面机器字长有限,表示数的范围有限,不可能表示理论数学上的所有的数。另一方面内存空间有限,把数据划分为不同的类型可以更有效的编码数据并可以更好地利用内存空间。
− 不同数据有不同的运算。划分数据类型意味着约定不同类型的数据都可以进行哪些运算。
• 大多数语言都定义了两类数据类型:
− 简单数据类型
简单数据类型有时也称原子类型、基本类型、标量类型或内建类型,其值不能再分解。简单数据类型通常有整数类型、实数类型、字符类型、布尔类型等。
− 复合数据类型
复合数据类型是一组元素,其中每个元素是简单数据类型或复合数据类型。复合数据类型通常有数组、记录、类、文件等。

Java的数据类型

类型和值的种类
• PrimitiveType
− 基本类型(原始类型、简单类型),基本类型的值不可再分解
− Java的基本数据类型是由Java编程语言预定义的,并通过其保留的关键字命名
− 整数类型、浮点数类型、布尔类型
• ReferenceType
− 引用类型(实际上就是“复合数据类型”)
− 引用类型是用来表示对象或数组的引用的
− 类类型、接口类型、类型变量、数组类型
• 还有一种特殊的类型——空类型
− 空类型表示“空”,表达式为null
− 空类型没有名字

类型转换

• 运算符和操作数的组合形成了表达式。
• Java中的表达式要么不产生任何结果,要么产生一个可以在编译时推断出来的类型的值。
• 当表达式出现在特定上下文时,它的值的类型要与向下文所期望的类型兼容,这个类型被称为目标类型。
• 表达式与其周围上下文的兼容性可以借助下面两种方式实现:
− 首先,对于合成表达式,推断出来的类型可能受到目标类型的影响,因此相同的表达式在不同的上下文中可能会有不同的类型。
− 其次,在表达式的类型被推断出来后,会执行从表达式的类型到目标类型的隐式类型转换。
− 如果这两种策略都无法产生恰当的类型,那么就会产生编译时错误。

常量

计算机本质上是用来做计算的,程序中的很多概念是源于数学计算。看一个函数的例子。
image.png
这是计算圆的周长的公式,R是圆的半径,C是周长。其中,R和C都是变量,2和都是常量。而且还可以看到,常量可能是用数字表示,也可能是用字母表示。
程序中变量和常量的概念与此相同。
在程序运行过程中,其值不能改变的量叫常量。
Java中的常量有两种
• 字面量
− 十进制数1000;布尔值true、false;英文字符‘a’,空值null等
• 最终变量
− 用修饰符final修饰的变量
final double PI = 3.14;

变量

在程序运行过程中,其值可能会改变的量叫变量。
从实现的角度看,变量是利用声明的方式,将内存中的某块存储空间保留下来以供程序使用,用来存放数据。变量名就是这块存储空间的名字。
变量的声明与使用
• 变量必须先声明,后使用
• 变量的声明包括如下四个要素:
− 变量名、变量类型、变量的初值、变量的属性
• 变量声明语句的格式
− 类型 变量名[,变量名][=初值]

  1. package com.buptnu.demos;
  2. public class VarEg {
  3. public static void main(String[] args) {
  4. double r = 10;
  5. double c;
  6. final double PI = 3.14;
  7. c = 2 * PI * r;
  8. System.out.println(c);
  9. }
  10. }

基本数据类型

Java提供了8种基本数据类型,利用基本数据类型可以构造出复杂的数据结构来满足需要。

数据类型 类型名 位长 默认值 取值范围
布尔型 boolean 1 false true,false
字节型 byte 8 0 -128~127
字符型 char 16 ‘\u0000’ ‘\u0000’~‘\uffff’,’\u0000’~’\uffff’,即从0到65535
短整型 short 16 0 -32768~32767
整型 int 32 0 -2,147,483,648 ~ 2,147,483,647
长整型 long 64 0 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
符点型 folat 32 0.0 1.4E-45~3.402 823 5E+38
双精度 double 64 0.0 4.9E-324 ~ 1.797 693 134 862 315 7E+308

整数类型

• 整数类型
− byte、short、int、long、char
• 整数的运算
− (1)算数运算

运算符 功能 举例 说明
取正 +x 单目运算,将x取正
取负 -x 单目运算,将x取负
5+3 → 8 双目运算
5-3 → 2 双目运算
* 5*3 → 15 双目运算
5/3 → 1 双目运算,整数相除取商的整数部分
% 求余 5%3 → 2 双目运算,两数项除取余数

− (2)自增运算++和自减运算- -

运算符 功能 举例 说明
++ 加1 i++, ++i 单目运算,等价于i=i+1
-- 减1 i--,--i 单目运算,等价于i=i-1

− (3)算术赋值运算符

运算符 功能 举例 等价于
+= 左边数加右边数,结果赋给左变量 x+=10 x=x+10
-= 左边数减右边数,结果赋给左变量 x-=10 x=x-10
*= 左边数乘右边数,结果赋给左变量 x*=10 x=x*10
/= 右边数除左边数,结果赋给左变量 x/=10 x=x/10
%= 右边数除左边数,余数赋给左变量 x%=10 x=x%10

− (4)关系运算

运算符 功能 举例 说明
> 大于 5>3 → true 产生boolean类型的值
< 小于 5<3 → false 产生boolean类型的值
>= 大于等于 5>=3 → true 产生boolean类型的值
<= 小于等于 5<=3 → false 产生boolean类型的值
== 等于 5==3 → false 产生boolean类型的值
!= 不等于 5!=3 → true 产生boolean类型的值

− (5)条件运算
条件运算符是三元运算符,用“?”和“:”表示。
条件表达式的结构如下:
(条件)?结果1:结果2
− (6)位运算符

运算符 含义 举例 说明
~ 位非 ~a 对a的每一位求反,即1 变0,0变1
& 位与 a&b 将a和b的对应位进行与运算。两个操作数中,如果两个相应位都为1,则该位的结果位1,否则为0
| 位或 a|b 将a和b的对应位进行或运算。两个操作数中,只要两个相应位中有一个为1,则该位的结果位1,否则为0
^ 位异或 a^b 将a和b的对应位进行异或运算。两个操作数中,如果两个相应位相同,则结果位0,否则为1
<< 位左移 a<<b 将a的二进制位序列左移b位,高位左移后溢出,舍弃不用。低位补0
>> 位右移 a>>b 将a的二进制位序列右移b位,移到右端的低位被舍弃,最高位则移入原来的最高位
>>> 位添零右移 a>>>b 将a的二进制位序列添零右移b位,移到右端的低位被舍弃,最高位则移入0

− (7)类型转换运算
可以将整数值转换为任何指定的数字类型
− (8)字符串连接运算
“abc”+3

浮点类型

浮点类型
• float、double
浮点数的运算
• (1)算数运算
• (2)自增运算++和自减运算- -
• (3)算术赋值运算符
• (4)关系运算
• (5)条件运算
• (6)类型转换运算
• (7)字符串连接运算
− “abc”+3.14

布尔类型

布尔类型
• Boolean
布尔值运算
• 逻辑运算(布尔运算)
• 条件运算符 ? :
• 字符串连接运算符 +
逻辑运算(布尔运算)

运算符 含义 举例 说明
! 逻辑非 !(3>5) → true 当!符号后面的表达式的值为真时,整个逻辑表达式的值为假。当!符号后面的表达式的值为假时,整个逻辑表达式的值为真。
&& 逻辑与 (3<5)&&(6>4) → true 仅当&&连接的两个表达式的值都为真时,整个逻辑表达式的值才为真。运算时,如果左边表达式的值为假,则判定整个表达式的值为假,不再计算右边表达式的值。
|| 逻辑或 (3>5)||(6<4) → false 仅当||连接的两个表达式的值都为假时,整个逻辑表达式的值才为假。运算时,如果左边表达式的值为真,则判定整个表达式的值为真,不再计算右边表达式的值。
& 布尔逻辑与 (3<5)&(6>4) → true 在表达式判定上,与&&相同,但是它总是计算两边表达式的值。
| 布尔逻辑或 (3>5)|(6<4) → false 在表达式判定上,与||相同,但是它总是就算两边表达式的值。

一个变量与数据类型值的例子

  1. package com.buptnu.demos;
  2. public class CTypes {
  3. public static void main(String[] args) {
  4. byte b=0x55;
  5. short s=0x55ff;
  6. int i=1000;
  7. long l=0xffffL;
  8. char c='c';
  9. float f=0.23F;
  10. double d=0.7E-3;
  11. boolean B=true;
  12. String S="This is a string.";
  13. System.out.println("字节型变量b="+b);
  14. System.out.println("短整型变量s="+s);
  15. System.out.println("整型变量i="+i);
  16. System.out.println("长整型变量l="+l);
  17. System.out.println("字符型变量c="+c);
  18. System.out.println("浮点型变量f="+f);
  19. System.out.println("双精度变量d="+d);
  20. System.out.println("布尔型变量B="+B);
  21. System.out.println("字符串对象S="+S);
  22. }
  23. }

语句”byte b=0x55; “,是变量声明语句,其中byte是java中的关键字,它是字节型数据的数据类型名。b是变量名。0x55是常量,由于该常量是用0x开头的数字,按照我们前面讲过的,以0x开头的数字是十六进制数。等号=是赋值运算符,它的作用是把常量0x55赋给变量b。所以这条语句的作用是声明了一个字节型变量b,并且给它赋初值为0x55。从数据存储的角度看,这条语句实际上就是告诉计算机在内存中开辟一个8bit的存储空间,并把这个存储空间命名为b,然后把整数0x55存到名为b的存储空间中。
语句” short s=0x55ff; “和”int i=1000; “都不必多说了。它们分别声明了一个短整型变量s和一个整型变量i,并分别用常量,十六进制整数0x55ff和十进制整数1000赋了初值。
语句” long l=0xffffL; “中的常量0xffffL是十六进制整数0xffff,后面加上了大写字母L,表示它以64位的长整型数的形式给变量l赋值。
语句” float f=0.23F; “中的常量0.23F,是在0.23的后面加上了大写字母F,它表示把0.23作为float类型的实数赋给浮点型变量f。
语句” double d=0.7E-3; “中的常量0.7E-3,是使用科学计数法表示的实数0.7×10-3。
语句” boolean B=true; “中的常量true,表示Java直接使用单词true和false作为布尔型变量的值。
语句String S=”This is a string.”;比较特殊。在Java中,字符串不是基本的数据类型,它是作为字符串对象来处理的。在此,对字符串对象,我们只要了解这么多就可以了。这个程序中主要是为了让大家知道字符串常量和字符常量是由区别的。字符串常量用双引号括起来,如本语句中的”This is a string.”,而字符长量是用单引号括起来的,如本程序前面语句中的’c’。
程序小结:
① 字节型、短整型、整型和长整型变量都可以用来存放整数,只是它们占用的存储单元个数和表示数的范围不同。
② 在Java中,字符串不是基本的数据类型,它是作为字符串对象来处理的。

类型转换

下表列出了不会丢失信息的类型转换
有时需要把一种类型的数据转换成另一种类型的数据,转换方式有两种:
• 隐式类型转换(自动类型转换)
− int y;
− y = ‘a’;
• 显式类型转换(强制类型转换)
− double x = 3.0;
− int y = 0;
− y = (int)x;
为了满足上下文类型兼容性,简单类型数据和引用类型数据都有可能需要做类型转换。
Java的数据类型在定义的时候就已经决定,因此不能随意转换成其他的数据类型,但Java允许用户有限度地做类型转换处理。
一般程序设计语言中的数据类型转换可以分为“自动类型转换”和“强制类型转换”两种。但是Java不允许自动类型转换,只能进行强制类型转换。进行强制类型转换的方法是在表达式前加上由圆括号括起来的类型名:
(类型名) 表达式
例如有如下四行程序:
int a; // 声明一个整型变量a char b; // 声明一个字符型变量b b = ‘A’; // 把字符常量,大写的A赋给变量b a = (int) b; // 这一行是把变量b的值赋给变量a。在b之前的(int)告诉编译器,把字符型的b的值强制转换成整型,在把它放在变量a中
在进行类型转换时,要注意使目标类型能够容纳原类型的所有信息。举个例子,长整型的位长时64位,整型的位长时32位,长整型比整型有更多的信息,所以把长整型转换为整型可能会丢失信息,而把整型转换为长整型则不会丢失信息。

原始类型 目标类型
byte short,char,int,long,float,double
short int,long,float,double
char int,long,float,double
int long,float,double
long float,double
float double