本节主要介绍类的定义、类的构成和对象的创建及使用。
定义类就是要定义类的属性与方法。类可理解成Java中一种新的数据类型。它是Java程序设计的基本单位。Java定义类的语法格式如下。
[访问说明符] [修饰符] class 类名
{
成员变量声明 //描述对象的状态
成员方法声明 //描述对象的行为
}
其中,第一行被称为类的头部,下面用{ }括起来的部分被称为类的主体。
头部中的[访问说明符]和[修饰符]是任选项,它们的用法将在后面章节中介绍;头部中的class是必选项,是定义类的关键词;头部中的类名也是必选项,用于标识新产生的数据类型;类的主体部分包括成员变量和成员方法的声明。
下面通过一个具体的例子介绍定义类的方法,具体代码如下。
//定义职员类Employee
class Employee //类的头部
{ //类的主体部分
//声明成员变量
String employeeName; //职员姓名
double salary; //薪水
//声明成员方法
public void setEmployeeSalary(double d1){ //该方法用于设置职员薪水
Salary = d1;
}
}
注意事项 一个类的主体部分可以包含多个成员变量和成员方法,也可以没有。
成员变量的声明方式如下。
[访问说明符] [修饰符] 数据类型 变量名;
其中,访问说明符和修饰符是任选项,可根据需要进行取舍;数据类型是必选项,用于设置变量存储的数据类型,可以是任何有效的Java数据类型。变量名也是必选项,用于标识被声明的变量。
例如,在职员类Employee中,声明成员变量employeeName,具体代码如下。
String employeeName;
类的成员方法往往用来操作类的成员变量,实现类对外界提供的服务,也是类与外界交流的接口。成员方法包括两部分:方法头部和方法体。定义成员方法的语法格式如下。
[访问说明符] [修饰符] 返回值类型 方法名(参数列表) //方法头部
{
//方法体
局部变量声明;
语句序列;
}
例如,职员类Employee中的setEmployeeSalary()方法。
//该方法用于设置职员薪水
public void setEmployeeSalary(double d1){
Salary = d1;
}
该方法使用的访问说明符是public,方法返回值的类型为void,方法的名称是setEmployee-Salary,参数列表是一个double类型的变量d1,方法的主体部分是把形参变量d1的值赋值给类的成员变量salary。
类的成员方法简称方法,用来实现类的各种功能。在类中除了普通成员方法外,还有一种特殊的方法——构造方法,用来创建对象并完成新建对象的初始化任务。
定义构造方法的语法格式如下。
[访问说明符] 类名([参数列表])
{
//方法体
}
· 访问说明符: 可以表示访问权限的修饰词(public、protected、private和默认值等)。
· 类名: 类名即构造方法名。
· 参数列表: 构造方法的参数可以有多个,也可以没有。
· 方法体: 完成成员变量初始化工作的语句,也可以为空。
定义构造方法的示例代码如下。
//无参数的构造方法
public Employee(){
}
//有参数的构造方法
public Employee(String name){
employeeName = name;
System.out.println("带有姓名参数的构造方法被调用!");
}
注意事项 构造方法是一种特殊的方法,在定义时有两点需要注意:①构造方法的名称必须与类名一样;②构造方法没有返回类型,也不能定义为void。
Java的每个类至少有一个构造方法。如果程序员没有定义构造方法,系统会自动为这个类创建一个默认的构造方法。这个默认构造方法没有参数,而且方法体中也没有任何代码。
例如,下面定义类的两种写法效果完全一样。
//开发人员在类中没有定义构造方法
class Customer{
}
//开发人员在类中定义了一个无参的,并且方法体为空的构造方法
class Customer{
public Customer(){
}
}
对于第一种写法,开发人员虽然没有定义构造方法,但系统会自动添加一个无参的、方法体为空的构造方法。因此,上述两种写法效果完全一样。
在Java应用程序中可以包含多个类,每个类可以有多个方法,但编译器首先运行的是main()方法。含有main()方法的类被称为主控类(主类),主类的类名必须与所在的文件名一致。
main()的语法格式如下。
public static void main(String args[]){
…
}
在main()方法的括号里面有一个形式参数args[]。args[]是一个字符串数组,可以接收系统传递的参数,而这些参数来自于命令行参数。
在命令行执行一个Java应用程序的语法格式如下。
java 类名 [参数列表]
其中,参数列表可以容纳多个参数,参数间以空格或制表符隔开,被称为命令行参数。系统传递给main()方法的实际参数正是这些命令行参数。
由于Java中数组的下标是从0开始的,所以形式参数中的args[0],…,args[n-1]依次对应第1个,…,第n个参数。参数与args数组的对应关系如下所示。
下面通过一个示例演示main()方法是如何接收命令行参数的。
【例3-1】命令行参数的使用。
功能实现:通过命令行向主方法传递两个参数,并输出参数的值。
public class Test_CommandLine_Arguments {
public static void main(String args[]){
//依次获取命令行参数,并输出
System.out.println("第一个参数: " + args[0]);
System.out.println("第二个参数: " + args[1]);
}
}
在Eclipse运行程序之前,首先要在Eclipse的“Run Configurations”对话框中设置命令行参数的值,如图3-6所示。
命令行参数设置完毕后,单击Run按钮运行程序,结果如图3-7所示。
图3-6 命令行参数设置
图3-7 例3-1运行结果
注意事项 在命令行参数中,所有参数都是以字符串形式传递的,各参数以空格分隔。
对象的声明就是确定对象的名称,并指明对象所属的类,语法如下。
类名 变量名列表;
示例代码如下。
Employee employee; //声明成员变量
注意事项 变量名列表可包含一个对象名或多个对象名,如果含有多个对象名,对象名之间采用逗号分隔开。
在声明对象时,并没有为对象分配内存空间。只有通过new运算符调用构造方法才能完成对象的创建,并为该对象分配内存空间。
对象创建的语法如下。
对象名 = new 构造方法([实参列表]);
示例代码如下。
employee = new Employee("100001"); //创建工号为100001的员工
声明并创建对象的目的就是为了使用它。对象的使用包括使用其成员变量和成员方法,运算符“.”可以实现对成员变量的访问和成员方法的调用。成员变量和成员方法使用语法如下。
对象名.成员变量名;
对象名.成员方法名([实参列表]);
示例代码如下。
employee.employeeName ="张三"; //使用成员变量
employee. setEmployeeSalary(9600);//调用成员方法
一旦定义了成员变量,就能对其进行初始化和其他操作。
(1)在同一个类中使用成员变量
class Camera{
int numOfPhotos; //照片数目
public void incrementPhotos(){ //增加照片的个数
numOfPhotos++; //使用成员变量numOfPhotos
}
}
(2)在另外一个类中使用成员变量
通过创建类的对象,然后使用“.”操作符指向该变量,例如:
class Robot{
Camera camera; //声明Camera的对象
public void takePhotos(){ //拍照功能的成员函数
camera = new Camera(); //给camera对象分配内存
camera.numOfPhotos++; //使用cameral对象的成员变量numOfPhotos
}
}
调用成员方法必须是方法名后跟括号和分号,示例代码如下。
camera. incrementPhotos(); //调用camera对象的成员函数
(1)调用同类的成员方法
class Camera{
int numOfPhotos; //照片数目
public void incrementPhotos(){ //增加照片的个数
numOfPhotos++; //使用成员变量numOfPhotos
}
public void clickButton(){
incrementPhotos();//调用同类的成员方法incrementPhotos()
}
}
(2)调用不同类的成员方法
通过创建类的对象,然后使用“.”操作符指向该方法。示例如下。
class Robot{
Camera camera;//声明Camera的对象
public void takePhotos(){ //拍照功能的成员函数
camera = new Camera(); //给camera对象分配内存
//增加照片个数
camera.clickButton(); //使用cameral对象的成员函数clickButton()
}
}
Java中所有基本数据类型的参数都是传值的,这意味着参数的原始值不能被调用的方法改变。下面通过一个例子演示传值调用的方法。
【例3-2】自定义类SimpleValue,实现基本类型数据的参数传递。
程序运行结果如图3-8所示。
图3-8 例3-2的运行结果
程序分析: 执行change()方法后,不会改变main()方法中传递过来的变量x的值,因此最后的输出结果仍然是5。由此可见,在传值调用过程中,参数值的一份拷贝传给了被调用方法,把它放在一个独立的内存单元。因此,当被调用的方法改变参数的值时,这个变化不会反映到调用方法里。
对象的引用并不是对象本身,它只是对象的一个句柄(名称)。一个对象可以有多个句柄,就好像一个人可以有多个姓名(如中文名、英文名等)。下面通过一个示例演示引用传递的方法。
【例3-3】自定义类ReferenceValue,实现引用数据的参数传递。
class ReferenceValue{
int x ;
public static void change(ReferenceValue obj){
obj.x=4;
}
public static void main(String [] args) {
ReferenceValue obj = new ReferenceValue();
obj.x = 5;
System.out.println("chang方法调用前的x = " + obj.x);
change(obj);
System.out.println("chang方法调用后的x = " + obj.x);
}
}
程序运行结果如图3-9所示。
图3-9 例3-3的运行结果
程序分析: main()方法中首先生成obj对象,并给其成员变量x赋值为5。接下来调用类中定义的方法change()。在change()方法调用时把main()方法的obj的值赋给change()方法中的obj,使其指向同一内容。change()方法结束,change()中的obj变量被释放,但堆内存的对象仍然被main()方法中的obj引用,就会看到main()方法中的obj所引用的对象的内容被改变。
注意事项 Java语言中基本类型数据传递是传值调用,对象的参数传递是引用调用。
当一个对象被创建时,它的成员变量会按照表3-1所示的列表进行初始化赋值。
表3-1 对象的成员变量的初始值
下面通过一个示例演示Employee类对象的创建及使用。
【例3-4】职员类Employee类对象的创建及使用。
功能实现: 定义一个职员类Employee,声明该类的三个对象,并输出这三个对象的具体信息。
程序运行结果如图3-10所示。
图3-10 例3-4的运行结果
程序分析: 测试类Test_Employee包含一个main()方法,该方法实现对Employee类的对象的操作。在main()方法中声明和创建了三个Employee类的对象employee1、employee2和employee3。它们是完全独立的对象,每个对象都有自己的成员变量。成员变量的值可以通过方法修改,也可以使用默认值进行初始化。在对象调用某个方法时,该方法所访问的成员变量都是这个对象自身的成员变量。