三、Java中的变量

1.变量的定义:
在程序运行期间,随时可能产生一些临时数据,应用程序会将这些数据保存在一些内存单元中每个内存单元用一个标识符来标识。

这些内存单元被称为变量,定义的标识符就是变量名,内存单元中存储的数据就是变量的值。

变量的定义

int x = 0, y;
y = x + 3;

第一行代码的作用是定义两个变量x和y,相当于分配了两块内存单元,在定义变量的同时为变量x分配了一个初始值0,而变量y没有分配初始值。
第二行代码的作用是为变量赋值,在执行第二行代码时程序先取出变量x的值,与3相加后,将结果赋值给变量y。

变量x和y在内存中的变化

java 写入临时文件 造成无法响应_取值范围

2.变量的数据类型
Java是一门强类型的编程语言,它对变量和数据类型有严格的限定。在定义变量时必须声明变量的类型,在为变量赋值时必须赋予和变量同一种类型的值,否则程序会报错。

Java中的变量数据类型分为两种:基本数据类型和引用数据类型

java 写入临时文件 造成无法响应_取值范围_02

8种基本数据类型是Java语言内嵌的,在任何操作系统中都具有相同大小和属性,而引用数据类型是在Java程序中由编程人员自己定义的数据类型。

(1)整数类型变量
整数类型变量用来储值整数数值,既没有小数部分的值。在Java中为给不同大小范围内的整数合理地分配存储空间,整数类型分为4种不同的类型:
字节型(byte)
短整型(short)
整型(int)
长整型(long)

4种类型所占存储空间的大小以及取值范围

java 写入临时文件 造成无法响应_赋值_03


占用空间指的是不同类型的变量分别占用的内存大小。取值范围是变量存储的值不能超出的范围。

注意:在为一个long类型变量赋值时,所赋值的后面要加上一个字母L或小写l,说明赋值为long类型。如果赋值为超出int的取值范围,可以省略字母L。

long num = 2200000000L;  //所赋值超出int型的取值范围,后面必须加上字母L
long num = 198L;         //所赋值未超出int型取值范围,后面可以加上字母L
long num = 198;          //所赋值未超出int型取值范围,后面可以省略字母L

(2)浮点数类型变量
浮点数类型变量用来存储小数数值,浮点数类型分为两种:单精度浮点数(float)和双精度浮点数(double)。double表示的浮点数比float更精确。

2种类型浮点数所占存储空间的大小以及取值范围

java 写入临时文件 造成无法响应_取值范围_04

E表示以10为底的指数,E后面的+和-表示正指数和负指数。
例如:1.4E - 45 表示1.4 * 10^(-45)

在Java中一个小数默认为double类型,因此在为一个float变量赋值时需要注意所赋值后面一定要加上字母F(或者小写f),而为double赋值时可以在所赋值后面加上字母D(或者小写d),也可以不加。

float f = 123.4F;     //为一个float类型的变量赋值,后面必须加上字母F
double d1 = 100.1;    //为一个double类型的变量赋值,后面可以省略字母D
double d2 = 199.3D;   //为一个double类型的变量赋值,后面可以加上字母

在程序中也可以为一个浮点数类型的变量赋予一个整数的值,例如下面写法也是可以的

float f = 100;       //声明一个float变量并赋值整数
double d = 100;      //声明一个double变量并赋值整数

(3)字符型变量
字符型变量用于存储一个单一字符,在Java中用char表示。在Java中每个char类型的字符变量占用2个字节。在给char类型的变量赋值时,需要用一对英文半角格式的单引号吧字符括起来,如‘a’,也可以将char类型的变量赋值为0~65535范围内的整数,计算机会自动将这些整数转化为所对应的字符,如数值97对应的字符为’a’。

char c = 'a';    //为一个char类型的变量赋值为'a'
char ch = 97;    //为一个char类型的变量赋值整数97,相当于赋值字符'a'

(4)布尔类型变量
布尔类型的变量用来存储布尔值,在Java中用boolean表示,该类型变量只有两个值true和false。

boolean flag = false;    //声明一个boolean类型的变量,初始值为false
flag = true;             //改变flag的变量为true

3.变量的类型转换
在程序中,当吧一种数据类型赋值给另外一种数据类型时的变量时,需要进行数据类型转换。根据转换方式的不同,数据类型可分为两种:自动数据类型转换和强制数据类型转换。

(1)自动数据类型转换
自动数据类型转换也叫隐式类型转换,指的是两种数据类型在转换过程中不需要显示地进行声明。要实现自动类型转换,必须同时满足两个条件,第一两种数据类型彼此兼容,第二目标类型的取值范围大于源类型的取值范围。
例如:

byte b = 3;
int x = b;    //程序吧byte类型的变量b转换为int类型,无需特殊声明

上面语句中,byte类型的变量b的值赋给int类型的变量x,由于int类型的取值范围大于byte类型的取值范围,编译器在赋值过程中不会造成数据丢失,所以编译器能自动完成这种转换,在编译时不报任何错误。

还有很多类型之间可以互相转换,接下来列出3种可以自动转换类型的情况。
第一种:整数类型之间可以互相转换,如byte类型的数据可以赋值给short,int,long等类型的变量。short,char类型的数据可以赋值给int、long类型的变量,int类型的数据可以赋值给long类型的变量。
第二种:整数类型转化为float类型,如byte,char,short,int类型的数据可以赋值给float类型的变量。
第三种:其他类型转换为double类型,如byte,char,short,int,long,float类型的数据可以赋值给double类型的变量。

(2)强制类型转换
强制类型转换也叫显示类型转换,指的是两种数据类型之间的转换需要进行显示的声明。当两种类型彼此不兼容,或者目标类型取值范围小于源类型时,自动类型转换无法进行,这时需要强制数据类型转换。

public class Example01{
	public static void main(String[] args){
		int num = 4;
		byte b = num;
		System.out.println(b);
	}
}

程序运行结果

java 写入临时文件 造成无法响应_取值范围_05


出现这样错误的原因是将一个int型的值赋给byte类型的变量b时,int类型的取值范围大于byte类型的取值范围,这样的取值会导致数据溢出,也就是说一个字节的变量无法存储四个字节的整数值。

在这种情况下,就需要进行强制类型转换,格式如下
目标类型 变量 = (目标类型)值

将Example01.java 第4行代码修改如下

byte b = (byte) num;

再次编译后,程序不会报错,程序运行结果如下:

java 写入临时文件 造成无法响应_赋值_06


注意:在对变量进行强制类型转换时,会发生取值范围较大的数据类型向取值范围较小的数据类型的转换,如将一个int类型的数据转换为byte类型,这样做极容易造成数据精度的丢失。

public class Example02{
	public static void main(String[] args){
		byte a;    //定义byte类型的变量a
		int b = 298;  //定义int类型的变量b
		a = (byte) b;
		System.out.println("b="+b);
		System.out.println("a="+a);
	}
}

java 写入临时文件 造成无法响应_取值范围_07

在第五行发生了强制类型转换,将一个int类型的变量b强制转换为byte类型,然后在将强转后的结果赋值给a。从运行结果可以看出变量b本身的值为298,然后在赋值给变量a后,其值为42,明显丢失了精度。出现这种现象的原因是,变量b为int类型,在内存中占用4个字节,byte类型的数据在内存中占用一个字节。当将变量b的类型强转为byte类型后,前面3个高位字节的数据丢失,数值发生改变。

int类型转byte类型过程

java 写入临时文件 造成无法响应_赋值_08


int类型4个字节,8位为一个字节

298 转int类型二进制 00000000 00000000 00000001 00101010

int类型298强制转为byte类型 byte类型占用一个字节 二进制 00101010 转十进制42

(3)表达式类型自动提升
表达式是由变量和运算符组成的一个算式,变量在表达式中进行运算时,也有可能发生自动类型转换,这就是表达式数据类型的自动提升,如一个byte型的变量在运算期间类型会自动提升为int型。

public class Example03{
	public static void main(String[] args){
		byte b1 = 3;   //定义一个byte类型的变量
		byte b2 = 4;
		byte b3 = b1+b2;//两个byte类型的变量相加,赋值给一个byte类型的变量
		System.out.println("b3=" + b3);
	}
}

编译程序报错

java 写入临时文件 造成无法响应_取值范围_09


这是因为表达式b1+b2运算期间变量b1和b2自动提示为int型,表达式的运算结果也就成了int型,这时就运算结果赋值给byte型的变量就会报错,需要进行强制类型转换。

将第5行代码修改为

byte b3 = (byte)(b1 + b2);

运行结果

java 写入临时文件 造成无法响应_java 写入临时文件 造成无法响应_10

(4)变量的作用域

变量需要先定义后使用,但这并不意味着在变量定义之后的语句中一定可以使用该变量。变量需要在它的作用范围内才可以被使用,这个作用范围称为变量的作用域。在程序中,变量一定会被定义在某一对大括号中,该大括号所包含的代码区域就是这个变量的作用域。

java 写入临时文件 造成无法响应_赋值_11

public class Example04{
	public static void main(String[] args){
		int x = 12;  //定义了变量x
		{
			int y = 96;  //定义了变量y
			System.out.println("x is " + x); //访问了变量x
			System.out.println("y is " + y); //访问了变量y
		}
		y = x;  //访问变量x,为变量y赋值
		System.out.println("x is " + x); //访问了变量x
	}
}

编译程序报错

java 写入临时文件 造成无法响应_取值范围_12

出现错误的原因在于变量y赋值时超出了它的作用域。去掉第9行代码。

public class Example04{
	public static void main(String[] args){
		int x = 12;  //定义了变量x
		{
			int y = 96;  //定义了变量y
			System.out.println("x is " + x); //访问了变量x
			System.out.println("y is " + y); //访问了变量y
		}
		System.out.println("x is " + x); //访问了变量x
	}
}

运行结果

java 写入临时文件 造成无法响应_数据类型_13