1. 变量与赋值
在程序运行期间,随时可能产生一些临时数据,应用程序会将这些数据保存在内存单元中,每个内存单元都用一个标识符标识,这些用于标识内存单元的标识符就称为变量,内存单元中存储的数据就是变量的值。
下面通过具体的代码学习变量的定义。
int x ;
int y = 0 ;
2. 变量的数据类型
Java语言的数据类型可分为基本数据类型和引用数据类型。
2.1 存储单元
-
比特
计算机就是一系列的电路开关,每个开关存在两种状态:关(off)或开(on)。如果电路是开的,它的值是1;如果电路是关的,它的值是0。
一个0或者一个1存储为1个比特(bit),是计算机中最小的存储单元,简写b。
-
字节
字节(byte)是计算机中最基本的存储单元,每个字节由8个比特构成,简写B。
1B = 8b
1KB = 1024B
1MB = 1024KB
1GB = 1024MB
2.2 整数类型
“整型类型变量”用来存储整数数值,即没有小数部分的值。整数类型分为4种不同的类型,分别是字节型(byte)、短整型(short)、整型(int)和长整型(long),4种类型所占存储空间的大小以及取值范围(变量存储的值不能超出的范围)如下表所示。
数据类型 | 类型 | 占用空间 | 取值范围 |
字节型 | byte | 1个字节(8位) | -27 ~ 27-1 |
短整型 | short | 2个字节(16位) | -215 ~ 215-1 |
整型 | int | 4个字节(32位) | -231 ~ 231-1 |
长整型 | long | 8个字节(64位) | -263 ~ 263-1 |
Java的整型字面量有4种表示方法:
-
十进制数,如0、123。
-
二进制数,以0b或者0B开头的数,如0B0000100。
-
八进制数,以0开头的数,如0123。
-
十六进制数,以0x或0X开头的数,如0x123。
byte num1 = 100; //byte
short num2 = 200; //short
int num3 = 300; //int
long num4 = 400; //long
long num5 = 12345678900L; // long 所赋的值超出了int类型的取值范围,后面必须加上字母L
int num6 = 0b00001000; //二进制
int num7 = 0123; //八进制
int num8 = 0x123; //十六进制
2.3 浮点类型
浮点类型的数就是所谓的实数。
Java中有两种浮点类型数据,float型和double型,float占32位,double占Java中有两种浮点类型数据,float型和double型,float占32位,double占64位。float型称为单精度浮点型,double型称为双精度浮点型,它们符合IEEE754标准。
数据类型 | 类型名 | 占用空间 | 取值范围 |
单浮点型 | float | 4个字节(32位) | 1.4E-45 ~ 3.4E+38,-3.4E+38 ~ -1.4E-45 |
双浮点型 | double | 8个字节(64位) | 4.9E-324 ~ 1.7E+308, -1.7E+308 ~ -4.9E-324 |
浮点型字面值两种表示方法:
-
十进制形式,由数字和小数点组成。
-
科学计数法,如12e3、12e-3分别表示为12*103、12*10-3,e之前必须有数字,e之后必须为整数。
浮点型字面值默认是double,如果表示float型字面值数据,必须后面加上f或F,double型也可以加d或D。
float f = 123.4f; // 为一个float类型的变量赋值,后面必须加上字母f
double d1 = 100.1; // 为一个double类型的变量赋值,后面可以省略字母d
double d2 = 199.3d; // 为一个double类型的变量赋值,后面可以加上字母d
浮点型误差,浮点数计算会存在舍入误差,如果需要精确而无舍入误差的数字计算,可以用BigDecimal类。
double d = 2.0 - 1.1;
System.out.println(d); //结果:0.8999999999999999
BigDecimal x = new BigDecimal("2.0");
BigDecimal y = new BigDecimal("1.1");
BigDecimal z = x.subtract(y);
System.out.println(z); //结果:0.9
2.4 字符类型
字符是程序中可以出现的任何单个符号,Java使用Unicode(统一码)为字符编码,Unicode字符集包含ASCII码字符集。
在Java中,字符型变量用char表示,用于存储一个单一字符。Java中每个char类型的字符变量都会占用2个字节。在给char类型的变量赋值时,需要用一对英文半角格式的单引号(' ')把字符括起来,如'a'。
对于一些特殊字符不能用单引号直接括起来直接使用,需要用转义序列来表示,用反斜杠(\)表示转义,如' \n'表示换行、' \t'表示竖屏制表键,常见转义字符序列如下:
转义字符 | 说明 | 转义字符 | 说明 |
\' | 单引号字符 | \b | 退格 |
\'' | 双引号字符 | \r | 回车 |
\\ | 反斜杠字符 | \n | 换行 |
\f | 换页 | \t | 水平制表符 |
2.5 布尔类型
在Java中,使用boolean定义布尔型变量,布尔型变量只有true和false两个值。
定义字符型变量,具体示例如下。
boolean flag = false; // 定义一个布尔型的变量flag,初始值为false
flag = true; // 改变变量flag的值为true
2.6 字符串类型
字符串是字符序列,不属于基本数据类型,是一种引用类型。
Java中字符串通过String类实现的,可用String声明和创建一个字符串,通过双引号(" ")括起来。
两个字符串可以通过“+”号进行连接,还可以通过“+”将字符串和基本数据类型连接。
String str = "hello";
String name = "my name is "+ "zhangsan";
String age = "my age is " + 10;
3. 变量的类型转换
整型、浮点型、字符型数据可能需要混合运算或相互赋值,这就涉及到数据类型转换,数据类型转换分为自动类型转换和强制类型转换。
3.1 自动类型转换
自动类型转换也叫宽转换或隐式类型转换,它是指将具有较少位数的数据类型转换为具有较多位数的数据类型。
自动类型转换必须同时满足以下两个条件:
-
两种数据类型彼此兼容。
-
目标类型的取值范围大于源类型的取值范围。
byte b = 3;
int x = b;
使用byte类型的变量b为int类型的变量x赋值,由于int类型的取值范围大于byte类型的取值范围,编译器在赋值过程中不会造成数据丢失,所以编译器能够自动完成这种转换,在编译时不报告任何错误。
自动类型转换关系如下:
3.2 强制类型转换
强制类型转换也叫显式类型转换,强制类型转换是将位数较多的数据类型转换为位数较少的数据类型,其语法用圆括号运算符。
int num = 4;
byte b = num;
System.out.println(b);
程序提示数据类型不兼容,不能将int类型转换成byte类型,原因是将一个int类型的值赋给byte类型的变量b时,由于int类型的取值范围大于byte类型的取值范围,这样的赋值会导致数值溢出,也就是说1字节的变量无法存储4字节的整数值。
针对上述的情况,就需要进行强制类型转换,即强制将int类型的值赋值给byte类型的变量。强制类型转换格式如下:
目标类型 变量 = (目标类型)值
byte b = (byte) num; //将上述的第2行代码修改为此代码
3.3 表达式中类型自动提升
所谓表达式是指由变量和运算符组成的一个算式。变量在表达式中进行运算时,可能发生自动类型转换,这就是表达式数据类型的自动提升。例如,一个byte类型的变量在运算期间类型会自动提升为int类型。
一个byte类型的变量在运算期间类型会自动提升为int类型,具体代码如下所示。
byte b1 = 3; // 定义一个byte类型的变量
byte b2 = 4;
byte b3 = b1 + b2; // 两个byte类型变量相加,赋值给一个byte类型变量
System.out.println("b3=" + b3);
在表达式b1+b2运算期间,变量b1和b2都被自动提升为int类型,表达式的运算结果也就成了int类型,这时如果将该结果赋给byte类型的变量,编译器就会报错。解决数据自动提升类型的方法,就是进行强制类型转换。强制类型转换格式如下:
byte b3 = (byte) (b1 + b2);
4. 变量的作用域
变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域。
上图所示代码有两层大括号。其中,外层大括号所标识的代码区域就是变量x的作用域,内层大括号所标识的代码区域就是变量y的作用域。
5. 练习
要求用户从键盘输入一个double型数,输出该数的整数部分和小数部分。
public static void main(String[] args) {
System.out.println("请输入一个浮点数:");
Scanner input = new Scanner(System.in);
double d = input.nextDouble();
int x1 = (int)d;
double y1 = d - (int)d;
System.out.println("整数部分是:" + x1);
System.out.println("小数部分是(精度存在问题):" + y1);
BigDecimal x2 = new BigDecimal(String.valueOf(d));
BigDecimal y2 = new BigDecimal((int)d);
BigDecimal z = x2.subtract(y2);
System.out.println("小数部分是:" + z);
}