——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
黑马程序员——常量与变量
一 常量的概念及使用
在程序执行过程中,其值不能改变的量称为常量,分为字面常数与标识符常量两种。标识符常量被初始化后,其值就不允许再发生改变。字面常数是指Java程序中具体的数值,如100、12.3、'A'、true等,它会存储在内存中的某个位置,用户将无法改变它的值。
Java语言中的常量值是用文字串表示的,可分为整型常量(如100、−120)、浮点型常量(如12.3、4.56f)、字符常量(如'A')、布尔常量(如true)和字符串常量(如"MingRi")等。
在Java语言中声明一个常量,除了要指定数据类型外,还需要通过final关键字进行限定,声明语法如下:
final type 标识符
也可以在声明的同时为常量赋值:
final type 标识符=值
其中关键字final用来指定标识符为一个常量,type表示数据类型,如int、float等。
例如,圆周率的值在程序执行过程中是不会改变的,所以可以将一个标识符定义为一个常量来保存圆周率值,声明方法如下:
final float PI=3.1415926F
通过关键字final将PI声明为一个常量,float指定了PI常量的数据类型。
注意:按照Java编码规范,常量名通常用大写表示,并且要符合“见其名知其意”的规则。
通过final关键字声明的常量,不能再改变其值,否则编译出错。
例如,声明final常量,程序代码如下。
public static void main(String[] args) {
final int NUM=100;
NUM = 20;
}
编译这段程序,会出现编译错误,如图所示。
二 变量的概念及命名规则
变量的使用是程序设计中一个十分重要的环节。为什么要定义变量呢?简单地说,就是要告诉编译器(Compiler)这个变量是属于哪一种数据类型的,这样编译器才知道需要配置多少空间给它以及它能存放什么样的数据。在程序运行过程中,空间内的值是变化的,这个内存空间就称为变量。为了便于操作,给这个空间取个名字,称为变量名。变量的命名必须是合法的标识符。内存空间内的值就是变量值。在声明变量时可以不赋值,也可以是直接赋予了初值。
例如,声明变量,程序代码如下。
int age; //声明int型变量
char char1 = ‘r’; //声明char型变量并赋值
编写以上程序代码,会产生什么样的作用呢?要了解这个问题,就需要对变量的内存配置有一定的认识。笔者用图解的方式,将上例程序代码在内存中的状况表现出来。
图 变量占用的内存空间
由图可知,系统的内存可大略分为3个区域,即系统区(OS)、程序区(Program)、数据区(Data)。当程序执行时,程序代码会加载到内存中的程序区,数据暂时存储在数据区中。假设上述两个变量定义在方法体中,则程序加载到程序区中。当执行此行程序代码时,会在数据区配置空间给这两个变量。
对于变量的命名并不是任意的,应遵循以下几条规则。
(1)变量名必须是一个有效的标识符
在Java语言中一个有效的标识符,通常是以大小写英文字母、数字、下画线“_”和美元符号“$”组成的,有关标识符的介绍请查看3.4节,例如:
int num1,num2;
float bookprice_$;
String userName;
//以下变量的命名则是非法的:
int 1num,2num; //无效变量名, 不能以数字开头
float book-price; //无效变量名, 包含了非法字符
说明:
在Java语言中,允许使用汉语中的文字和其他语言文字作为变量名,如“int年龄=24”是合法的,但建议读者不要使用这些语言文字作为变量名。
(2)不能声明多个相同的变量名
下面在同一个有效范围内,声明的变量名不允许重名,程序代码如下。
public static void main(String[] args) {
int num1,num2;
float num1; //编译出错, 局部变量num1重复
char ch,ch; //编译出错, 局部变量ch重复
}
Java语言中的标识符是区分大小写的,所以下面的变量名是合法的:
int num,Num; //声明了两个不同的变量
(3)变量名不能命名为Java关键字
关键字因在Java语言中有着特殊用途而被保留起来,在声明变量时,不能用来当做变量名称,在3.4.2 节会向大家介绍Java中的关键字。
(4)选择有意义的变量名
根据以上规则可以命名一个合法的变量名,在此基础上,建议读者尽量以有意义的名称来为变量命名,以便能够起到“见其名而知其意”的目的,使得程序代码更容易阅读,如“name”、“age”等。
变量的有效范围
变量的有效范围是指程序代码能够访问该变量的区域,若超出该区域访问变量,则编译时会出现错误。变量的有效范围决定了变量的生命周期,变量的生命周期是指从声明一个变量并分配内存空间开始,到释放该变量并清除所占用的内存空间结束。进行变量声明的位置,决定了变量的有效范围,根据有效范围的不同,可以将变量分为以下两种。
成员变量:在类中声明,在整个类中有效。
局部变量:在方法内或方法内的某代码块(方法内部,“{”与“}”之间的代码)中声明的变量。在代码块声明的变量,只在当前代码块中有效;在代码块外、方法内声明的变量在整个方法内都有效。
下面先通过如下代码初步了解成员变量和局部变量的声明及使用范围。
【例】 创建类Olympics,分别在类体中定义成员变量medal_All,局部变量medal_CN与gold,程序代码如下。
public class Olympics {
private int medal_All=800; //成员变量
public void China(){
int medal_CN=100; //方法的局部变量
if(true){ //代码块
int gold=50; //代码块的局部变量
medal_CN+=50; //允许访问
medal_All-=150; //允许访问
}
gold=100; //编译出错
medal_CN+=100; //允许访问
medal_All-=200; //允许访问
}
public void Other(){
medal_All=800; //允许访问
medal_CN=100; //编译出错, 不能访问其他方法中的局部变量
gold=10; //编译出错
}
}
由于本实例中定义的变量medal_CN与gold是局部变量,只有在定义的区域内有效,因此编译本实例中会出现错误,如图所示。
图 实例的编译错误提示
要避免在程序开发中出现这样的问题,就要很好地掌握成员变量与局部变量的定义和作用范围。
1.成员变量
类的成员变量又可分为两种:静态变量和实例变量。静态变量是指通过static关键字进行修饰的成员变量,没有被static关键字修饰的变量为实例变量。它们的区别如下:
静态变量的有效范围是整个类,并且可以被类的所有实例共享,可以通过“类名.变量名”的方式来访问静态变量。静态变量的生命周期取决于类的生命周期,当加载类时,为类中的静态变量分配内存空间,当卸载类时,释放静态变量占用的空间,静态变量被销毁。加载类时,会为静态变量分配内存空间,之后无论创建了多少类的实例,都不会再为静态变量分配内存空间,这些实例会使用同一个静态变量。
实例变量与类的实例对应,它的有效范围是整个实例。每创建一个类的实例,就会为当前实例分配实例变量的内存空间,所以实例变量的生命周期取决于实例的生命周期,实例被创建时,实例变量会被分配内存空间,当销毁实例时,释放实例变量占用的内存空间。
下面通过代码介绍静态变量与实例变量的区别。
先来创建一个类,并声明一个实例变量和一个静态变量,程序代码如下。
public class Student{
public static int amount=100; //声明一个静态变量amount
public int age=24; //声明一个实例变量age
}
然后,创建Student类的两个实例,代码如下:
Student st1=new Student();
Student st2=new Student();
此时,在Java虚拟机的运行时数据区中为Student类的两个实例及静态变量、实例变量进行的空间分配如图所示。
图 变量更改前Java虚拟机运行时数据区
下面分别通过引用变量st1和st2,来修改各自所引用实例中的实例变量age,并通过st2引用变量来修改静态变量amount,代码如下:
st1.age+=2;
st2.age+=3;
st2.amount+=100; //或通过类名进行访问: Student.amount+=100
此时的Java虚拟机的运行时数据区中存储的两个实例的实例变量及类的静态变量的值发生了改变,如图所示。
图 变量更改后Java虚拟机运行时数据区
2.局部变量
在类的方法中声明的变量,包括方法的参数,都属于局部变量,它们只在当前的方法内有效,不能用于类的其他方法中。在方法的代码块中声明的变量也是局部变量,但它只在该代码块内有效。
局部变量的生命周期取决于方法,当方法被调用时,Java虚拟机为方法中的局部变量分配内存空间,当方法的调用结束后,则释放该方法中局部变量占用的内存空间,局部变量被销毁。
可以声明一个与成员变量同名称的局部变量,此时在方法中访问该变量,针对的是方法中的局部变量,若没有在方法中声明与成员变量同名称的局部变量,在方法中访问该变量时,针对的是成员变量。
【例】 创建类Access,在该类中定义int型成员变量times与order,并在程序的主方法中定义局部变量times,分别输出变量times和order,程序代码如下。
public class Access{
private int times=3;
private static int order=2;
public static void main(String[] args) {
int times=5;
System.out.println("变量times的值为:"+times);
//输出结果
System.out.println("变量order的值为:"+order);
//输出结果
}
}
在命令标识符下编译运行本实例,运行结果如图所示。
图 本实例的运行结果
注意:
在声明及访问局部变量时,需要注意,在声明时,不能使用public、protected、private和static关键字对局部变量进行修饰,不能通过类名或引用变量来访问局部变量。