变量与常量

在程序执行过程中,其值不能被改变的量称为常量,其值能被改变的量称为变量。变量与常量的命名都必须使用合法的标识符。本节将向读者讲解标识符与关键字、变量与常量的声明、变量的有效范围。

标识符和关键字

标识符

标识符可以简单地被理解为一个名字,它是用来标识类名、变量名、方法名、数组名、文件名的有效字符序列。

Java 语言规定标识符由任意顺序的字母、下画线(_)、美元符号($)和数字组成,并且第一个字符不能是数字。标识符不能是 Java 中的关键字(保留字)。

下面是合法标识符:

name
user_age
$page
bash

下面是非法标识符:

4word
String
User name
bash

在 Java 语言中,标识符中的字母是严格区分大小写的,如 good 和 Good 是不同的两个标识符。Java 语言使用 Unicode 标准字符集,最多可以标识 65535 个字符。因此,Java 语言中的字母不仅包括通常的拉丁文字 a、b、c 等,还包括汉语、日语以及其他许多语言中的文字。

关键字

关键字又称保留字,是 Java 语言中已经被赋予特定意义的一些单词,不可以把这些单词作为标识符来使用。3.2 节介绍数据类型时提到的 int、boolean 等都是关键字。Java 语言中的关键字如表 3.4 所示。

image 2023 12 12 14 31 05 534
Figure 1. 表3.4 Java关键字

声明变量

变量的使用是程序设计中一个十分重要的环节。声明变量就是要告诉编译器(compiler)这个变量的数据类型,这样编译器才知道需要配置多少空间给它,以及它能存放什么样的数据。在程序运行过程中,空间内的值是变化的,这个内存空间就称为变量。为了便于操作,给这个空间取个名字,称为变量名。变量名必须是合法的标识符。内存空间内的值就是变量值。在声明变量时可以不用赋值,也可以直接赋予初值。

例如,声明一个整数类型变量和声明一个字符类型变量,代码如下:

int age;        // 声明int型变量
char char1 = 'r'; // 声明char型变量并赋值
java

编写以上程序代码,究竟会产生什么样的效果呢?要了解这个问题,就需要对变量的内存配置有一定的认识。用图解的方式将上述程序代码在内存中的状况表现出来,如图3.2 所示。

由图3.2 可知,系统的内存大略可被分为 3 个区域,即系统(OS)区、程序(program)区和数据(data)区。当执行程序时,程序代码会被加载到内存的程序区中,数据暂时被存储在数据区中。假设上述两个变量被定义在方法体中,则程序被加载到程序区中。当执行此行程序代码时,会在数据区配置空间给出这两个变量。

image 2023 12 12 14 33 34 198
Figure 2. 图3.2 变量占用的内存空间

对于变量的命名并不是随意的,应遵循以下几条规则:

  • 变量名必须是一个有效的标识符。

  • 变量名不可以使用 Java 中的关键字。

  • 变量名不能重复。

  • 应选择有意义的单词作为变量名。

在 Java 语言中允许使用汉字或其他语言文字作为变量名,如 “int年龄= 21”,在程序运行时不会出现错误,但建议读者尽量不要使用这些语言文字作为变量名。

Java 10 提供了一个方便好用的新特性:使用 var 声明局部变量。使用 var 声明局部变量的语法如下:

var 变量名称 = 值
bash

需要注意的是,var 是关键字,它相当于一种动态类型。编译器会根据赋给变量的值推断出变量的类型,因此使用 var 声明局部变量时必须赋予值。例如,在 main() 方法中,先使用 var 声明一个变量,变量的值为 “好好学习,天天向上”,再使用输出语句输出这个变量的值。代码如下:

public class Demo {
  public static void main(String[] args) {
       var str = "好好学习,天天向上";
       System.out.println(str);
  }
}
java

运行结果如下:

好好学习,天天向上
bash

此外,还需要注意的是:var 不能用于声明成员变量,如图3.3 所示;使用 var 声明的局部变量不能作为方法的返回值,如图3.4 所示。

image 2023 12 12 14 38 07 305
Figure 3. 图3.3 var不能用于声明成员变量
image 2023 12 12 14 38 28 318
Figure 4. 图3.4 使用var声明的局部变量不能作为方法的返回值

声明常量

在程序运行过程中一直不会改变的量被称为常量(constant),通常也被称为 “final变量”。常量在整个程序中只能被赋值一次。在为所有的对象共享值时,常量是非常有用的。

在 Java 语言中声明一个常量,除了要指定数据类型,还需要通过 final 关键字进行限定。声明常量的标准语法如下:

final 数据类型 常量名称 [= 值]
java

常量名通常使用大写字母,但这并不是必需的。很多 Java 程序员使用大写字母表示常量,是为了清楚地表明正在使用常量。

例如,声明常量 π(程序中用 PI 表示),代码如下:

final double PI = 3.1415926D
java

当变量被 final 关键字修饰时,该变量就变成了常量,必须在定义时就设定它的初值,否则将会产生编译错误。从下面的实例中可看出变量与常量的区别。

【例3.5】尝试给常量赋值,观察是否会发生错误(实例位置:资源包\TM\sl\3\5)

在项目中创建类 Part,在类体中创建变量 age 与常量 PI。在主方法中分别对变量和常量进行赋值,通过输出信息可测试变量与常量的有效范围。

public class Part { 						//新建类Part
	//声明常量PI,此时如不对PI进行赋值,则会出现错误提示
	static final double PI = 3.14;
	static int age = 23; 					//声明int型变量age并进行赋值
	
	public static void main(String[] args) { 	//主方法
		final int number; 				//声明int型常量number
		number = 1235; 				//对常量进行赋值
		age = 22; 					//再次对变量进行赋值
		number = 1236; 				//错误的代码,因为number为常量,只能进行一次赋值
		System.out.println("常量PI的值为:" + PI); 			//将PI的值输出
		System.out.println("赋值后number的值为:" +number);	//将number的值输出
		System.out.println("int型变量age的值为:" + age); 	//将age的值输出
	}
}
java

运行结果如下:

Exception in thread "main" java.lang.Error: 无法解析的编译问题:
  final 局部变量 number 可能已经被赋过值
  at Part.main(Part.java:10)
bash

从这个结果中可以看到,Part 类被运行后发生了错误,异常日志中记载 Part 类出现编译问题,此编译问题正是常量 number 被二次赋值。

英文版原版的异常日志为:Exception in thread "main" java.lang.Error: Unresolved compilation problem:The final local variable number may already have been assigned at Part.main(Part.java:10)

变量的有效范围

由于变量被定义出来后只是暂存在内存中,等到程序执行到某一个点,该变量会被释放掉,也就是说变量有它的生命周期。因此,变量的有效范围是指程序代码能够访问该变量的区域,若超出该区域,则在编译时会出现错误。在程序中,一般会根据变量的 “有效范围” 将变量分为 “成员变量” 和 “局部变量”。

成员变量

在类体中所声明的变量被称为成员变量,成员变量在整个类中都有效。类的成员变量又可分为两种,即静态变量和实例变量。例如下面这段代码:

class Demo {
    int x = 45;
    static int y = 90;
}
java

其中,x 为实例变量,y 为静态变量(也被称为类变量)。如果在成员变量的类型前面加上关键字 static,这样的成员变量被称为静态变量。静态变量的有效范围可以跨类,甚至可到达整个应用程序之内。静态变量除了能在声明它的类内存取,还能直接以 “类名.静态变量” 的方式在其他类内使用。

局部变量

在类的方法体中声明的变量(方法内部定义,在 {} 之间的代码中声明的变量)称为局部变量。局部变量只在当前代码块中有效,也就是只能在 {} 之间的代码中使用它。

在类的方法中声明的变量,包括方法的参数,都属于局部变量。局部变量只在当前定义的方法内有效,不能用于类的其他方法中。局部变量的生命周期取决于方法,当方法被调用时,Java 虚拟机会为方法中的局部变量分配内存空间,当该方法的调用结束后,则会释放方法中局部变量占用的内存空间,局部变量也将会被销毁。

局部变量可与成员变量的名字相同,此时成员变量将被隐藏,即这个成员变量在此方法中暂时失效。

变量的有效范围如图3.5 所示。

image 2023 12 12 14 52 28 229
Figure 5. 图3.5 变量的有效范围

【例3.6】把成员变量“排挤掉”的局部变量(实例位置:资源包\TM\sl\3\6)

在项目中创建类 Val,并分别定义名称相同的成员变量与局部变量,当名称相同时成员变量将被隐藏。

public class Val { 								//新建类
	static int times = 3; 							//定义成员变量times
	public static void main(String[] args) { 			//主方法
		int times = 4; 							//定义局部变量times
		System.out.println("times的值为:" + times); 	//将times的值输出
	}
}
java

运行结果如下:

times的值为:4
bash

编程训练(答案位置:资源包\TM\sl\3\编程训练)

【训练3】比较字符和整数 比较 'g' 和 103 是否相等。

【训练4】输出连续的字符 在控制台中输出 “ABCDEFG”。