2.3 变量
程序在运行时,系统会为程序分配内存单元来存储各种数据。变量是一个基本的存储单元,变量中存储的数据是可以改变的。程序通过一个变量名来代表该变量存储的数据。变量都有一个作用域来定义变量的可见范围和生存期。
2.3.1 声明变量及初始化
在Java语言中,所有变量必须先声明后使用。变量声明的方法如下所示。
类型 标识符 [=值]
· 标识符。就是变量的名字,变量可以先声明再初始化。也可以在变量声明时用等号后跟一个值的方法来初始化。多个相同类型的变量一起声明时,变量名字中间用逗号分开。
· 类型。Java中的任何一种数据类型。
在下面的示例程序中,首先声明了几个变量,然后初始化这些变量并输出变量的值。程序的编写方法和步骤如下所示。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_10 3 { 4 public static void main(String[] args) 5 { 6 //定义两个int型变量a、b 7 int a,b; 8 //定义两个char型变量c、d并初始化 9 char c = 'M',d = 'N'; 10 //定义一个double型变量k 11 double k = 2.81952; 12 //定义三个byte型变量x、y、z,其中x、y初始化 13 byte x = 10,y = 20,z; 14 //初始化a 15 a = 1000; 16 //初始化b 17 b = 10000; 18 //初始化z 19 z = 110; 20 System.out.println("a的值为:" + a); 21 System.out.println("b的值为:" + b); 22 System.out.println("c的值为:" + c); 23 System.out.println("d的值为:" + d); 24 System.out.println("k的值为:" + k); 25 System.out.println("x的值为:" + x); 26 System.out.println("y的值为:" + y); 27 System.out.println("z的值为:" + z); 28 } 29 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_10.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_10.java
(4)输入下面的命令,运行这个程序。
java Sample2_10
(5)程序的运行结果如图2-10所示。
图2-10 Sample2_10的编译运行结果
除了上面例子中变量的静态初始化方式之外,还可以动态初始化变量。所谓动态初始化就是在变量声明时通过等号后跟一个表达式的方法动态地初始化变量。
例如,先定义三个变量a、b、c,然后初始化。接着再把这三个变量值的和赋值给变量sum。示例程序的编写方法和代码如下所示。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_11 3 { 4 public static void main(String[] args) 5 { 6 //定义三个整型变量a、b、c 7 int a,b,c; 8 a = 1; 9 b = 2; 10 c = 3; 11 //动态初始化变量sum,把a+b+c的值赋给sum 12 int sum = a + b + c; 13 //动态初始化变量res,把a*b*c的值赋给res 14 int res = a*b*c; 15 System.out.println("a的值为:" + a); 16 System.out.println("b的值为:" + b); 17 System.out.println("c的值为:" + c); 18 System.out.println("sum的值为:"+sum); 19 System.out.println("res的值为:"+res); 20 } 21 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_11.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_11.java
(4)输入下面的命令,运行这个程序。
java Sample2_11
(5)程序的运行结果如图2-11所示。
图2-11 Sample2_11的编译运行结果
例子中的变量sum动态初始化为三个int型变量a、b、c值的和,变量res动态初始化为a、b、c三个变量值的乘积。
2.3.2 变量的作用域
Java语言里大括号括起来的部分是一个代码块。代码块中的变量只在本代码块中可以使用。也就是说在一个大括号范围中定义的变量不能在这个大括号外使用。在一个代码段范围定义的变量,在其嵌套的子代码段中仍然可以使用。示例程序的编写方法和步骤如下所示。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_12 3 { 4 public static void main(String[] args) 5 { 6 int a = 100; 7 int b = 200; 8 //该大括号对里的代码为一个代码块 9 { 10 int x = 5; 11 int y = 6; 12 //在该代码块内部使用代码块外的变量b 13 y= b + 1; 14 System.out.println("输出x的值:" + x); 15 System.out.println("输出y的值:" + y); 16 } 17 } 18 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_12.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_12.java
(4)输入下面的命令,运行这个程序。
java Sample2_12
(5)程序的运行结果如图2-12所示。
图2-12 Sample2_12的编译运行结果
程序在void main(String[] args)这个函数体的大括号中定义了变量b,这个大括号包含的代码段就可以使用变量b。例如,程序中的y=b+1赋值语句。
如果是在一个大括号的外面使用了该大括号里定义的变量,这样就超出了变量的有效范围,程序编译时就会报错。示例程序代码编写方法和步骤如下所示。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_13 3 { 4 public static void main(String[] args) 5 { 6 int a = 100; 7 int b = 200; 8 //该大括号里的代码为一个代码块 9 { 10 int x = 5; 11 int y = 6; 12 } 13 b = a + y; //使用了代码块里的变量y 14 System.out.println(b); 15 } 16 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_13.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_13.java
编译出错,系统提示“找不到符号”。系统不能识别变量y,编译器把变量y视作是一个没有定义就使用的变量。变量的作用域只对该变量所在的大括号范围内有效,如图2-13所示。
图2-13 Sample2_13的编译运行结果
2.3.3 数据类型的自动转换
在一个表达式中,经常会有几种不同数据类型的值参与运算。首先看一个示例。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_14 3 { 4 public static void main(String[] args) 5 { 6 short a = 200; 7 short b = 10; 8 short c = a*b; //把两个short类型的值相乘,把结果赋给short型变量c 9 System.out.println(c); 10 } 11 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_14.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_14.java
编译的时候就会出现错误。在例子中a*b的值为2000,并没有超出short类型的表示范围。但是编译时编译器指出a*b是一个int型。这是因为Java对表达式里变量值的类型进行了自动提升,如图2-14所示。
图2-14 Sample2_14的编译运行结果
表达式在运算时,因为其中间值可能会超过任何一个操作数类型的表示范围,因此Java就自动对参与运算的数值类型进行了提升。例如,上面例子中的a*b在运算时,a和b的乘积有可能会超过short类型的取值范围,Java就自动把a和b的类型提升为int类型。
Java语言定义了表达式的类型提升规则如下所示。
· 表达式中有一个操作数为short型或byte型,则该表达式的结果为int型。
· 表达式中有一个操作数为long型,则该表达式的结果为long型。
· 表达式中有一个操作数为float型,则该表达式的结果为float型。
· 表达式中有一个操作数为double型,则该表达式的结果为double型。
示例程序的编写方法和步骤如下所示。
(1)新建一个文本文档,用记事本程序打开该文档并输入下面的程序。
1 // 代码实现 2 public class Sample2_15 3 { 4 public static void main(String[] args) 5 { 6 byte a = 5; 7 short b = 30; 8 int c = 100; 9 float d = 2.55f; 10 double e = 3.6528; 11 char f = 'M'; 12 long g = 800; 13 //把一个含有多种类型变量的表达式结果赋给double型变量result 14 double result = (a+b) - (g-c) + (d*e) + (a-f); 15 System.out.println("result的值为:" + result); 16 } 17 }
(2)单击“文件”|“保存”命令,保存这个文件。并把文件重命名为Sample2_15.java。
(3)打开命令提示符窗口,然后输入下面的命令并按“Enter”键编译程序。
javac Sample2_15.java
(4)输入下面的命令,运行这个程序。
java Sample2_15
(5)程序的运行结果如图2-15所示。
图2-15 Sample2_15的编译运行结果
根据Java语言表达式类型提升的规则,变量a是byte型,所以表达式a+b的类型自动提升为int型。变量g为long型,所以表达式g−c的类型自动提升为long型。变量e为double型,所以表达式d*e的类型自动提升为double型。变量a为int型,所以表达式a−f的类型自动提升为int型。(a+b) − (g−c) + (d*e) + (a−f)就变成了int型减long型加double型再加上int型。int型减long型的结果为long型,long型再加double型的结果为double型,double型和int相加的结果为double型。所以,整个表达式的计算结果就为double型。