4.2 类设计基础之对象篇

admin 2025-06-28 03:22:10

4.1 定义了类之后,就可以用类定义对象了,对象又称为实例。

4.2.1 对象的声明与创建

1、对象的声明

声明形式为:

类 对象名列表;

其中“ 类” 是已经定义的类,“ 对象列表 ” 是声明的对象,可以是一个,也可以是多个。

如 4.1的Person类 ,则可以用这个类来声明对象:

Person p1,p2;

如这条语句就声明了两个对象名p1和p2.声明对象后必须创建对象,才能使用对象。

2、对象的创建

对象创建的形式: new 构造方法()

“new” 运算符后面跟“构造方法()”就可以创建对象了。利用构造方法就可以创建Person类的对象,如:

new Person();

但是这个对象没有名字,还无法使用。可以通过赋值的形式给这个对象取一个名字。如前面定义的对象名p1,p2;可以用p1表示创建的对象:

p1 = new Person();

以后就可以通过p1来使用这个对象了。

也可以声明对象时创建对象,如:

Person p1 = new Person();

Person p2 = new Person();

4.2.2 对象的使用

使用对象的形式:

对象名.域

对象名.方法名( [ 实际参数列表 ] )

其中“ . "称为分量运算符。

每一个对象都有自己的属性和行为,就如同每个人都有属于自己的身份证号码。

创建一个对象后,这个对象就有自己的行为和属性。通过对象访问域和方法,只能是对象本身的与或方法,而不是其他对象的域或方法,就如同一个人不能干涉其他人一样。

如定义的对象1p和p2:

p1 = new Person();

p2 = new Person();

可以访问:p1.x 、 p1.y 、 p2.x 、 p2.y

p1.方法 、 p2.方法1

例:对象的声明、创建与使用

平面内有若干个点,已知每个点的位置。要求定义一个类来描述这些点,并对这些点进行平移。

//先定义一个Point类,来描述这些点

class Point{

//域(属性),点的位置

int x,y;

//声明方法

//获得x分量

int getX(){

return x;

}

//获取Y的分量

int getY(){

return y;

}

//对点进行移动的方法

void move( int offsetX,int offsetY){

x+=offsetX;

y+=offsetY;

}

}

public class Main{

public static void main(String args[]){

//声明对象

Point p1,p2;

//创建对象

p1 = new Point();

p2 = new Point();

System.out.println("p1表示的坐标为:(" +p1.x +"," + p1.y +")");

System.out.println("p2表示的坐标为:(" +p2.x +"," + p2.y +")");

System.out.println("改变p1和p2后的坐标为:");

//通过对象访问其中的域(属性)

p1.x=8;

p1.y=12;

p2.x=-16;

p2.y=-20;

System.out.println("p1表示的坐标为:(" +p1.x +"," + p1.y +")");

System.out.println("p2表示的坐标为:(" +p2.x +"," + p2.y +")");

//对象调用方法,对点进行移动

p1.move(2,-1);

System.out.println("对p1平移(2,-1)后的坐标为:");

//通过对象调用getX()方法和getY()方法获取对象的域值

System.out.println("(" + p1.getX() + "," + p1.getY() + ")");

p2.move(6,-2);

System.out.println("对p2平移(6,-2)后的坐标为:");

System.out.println("(" + p2.getX() + "," + p2.getY() + ")");

}

}

结果:

p1表示的坐标为:(0,0)

p2表示的坐标为:(0,0)

改变p1和p2后的坐标为:

p1表示的坐标为:(8,12)

p2表示的坐标为:(-16,-20)

对p1平移(2,-1)后的坐标为:

(10,11)

对p2平移(6,-2)后的坐标为:

(-10,-22)

因为域有默认值,所以刚创建的两个对象结果为(0,0)。

4.2.3 构造方法

创建对象通过" new "运算符调用类中的构造方法。如果类中没有相应的构造方法,则不能创建对象。所以,在定义类时应该定义构造方法。在一个类中可以定义多个构造方法,形成构造方法的重载。利用重载的构造方法可以创建不同初始状态的对象。

构造方法的定义如下:

方法名 ( [ 形参列表 ] ) {

方法体 }

构造方法没有“方法类型”,写 “void” 也不可以。“方法名” 必须与所在的类的类名一致。“形参列表” 和 “方法体” 与其他的方法的定义一样。

例:为Point 类增加构造方法。

class Point{

//域

int x,y;

//无参的构造方法

Point(){

x=0;

y=0;

}

//有两个参数的构造方法

Point( int x1, int y1){

x=x1;

y=y1;

}

//获取x的分量

int getX(){

return x;

}

//获取y的分量

int getY(){

return y;

}

//对点进行移动的方法

void move( int offsetX,int offsetY){

x+=offsetX;

y+=offsetY;

}

}

public class Main{

public static void main(String args[]){

//声明对象

Point p1,p2;

//调用第一个构造方法

p1 = new Point();

//调用第二个构造方法

p2 = new Point(3,4);

System.out.println("p1表示的坐标为:(" +p1.x +"," + p1.y +")");

System.out.println("p2表示的坐标为:(" +p2.x +"," + p2.y +")");

//对象调用方法,对点进行移动

p1.move(2,-1);

System.out.print("对p1平移(2,-1)后的坐标为:");

//通过对象调用getX()方法和getY()方法获取对象的域值

System.out.println("(" + p1.getX() + "," + p1.getY() + ")");

p2.move(6,-2);

System.out.println("对p2平移(6,-2)后的坐标为:");

System.out.println("(" + p2.getX() + "," + p2.getY() + ")");

}

}

结果为:

p1表示的坐标为:(0,0)

p2表示的坐标为:(3,4)

对p1平移(2,-1)后的坐标为:(2,-1)

对p2平移(6,-2)后的坐标为:(9,2)

从上例可以看出,通过构造方法创建了对象并对对象中的域进行了初始化。所以构造方法(构造器)相当于有两个作用:一个是创建对象,另一个是对对象进行初始化。

如果没有定义构造方法,也可以调用构造方法创建对象,因为在类中不定义构造方法,Java编译器会为类产生一个默认的构造方法,这个构造方法没有参数,方法体是一个空方法体。如果定义了构造方法,则Java编译器就不再提供默认的构造方法。

4.2.4 对象的内存模式

p2 = new Point(2,-1);表示创建了一个Point类,并用p2表示。

表达式 “new Point(2,-1)” 创建Point 类的对象,同时,整个表达式的值是这个对象在内存中的地址。但这个对象没有名字,无法使用。

语句“p2 = new Point(2,-1);” 是将对象 “new Point(2,-1)” 的地址保存在变量p2中,使用访问对象名p2就可以访问对象 “new Point(2,-1)”。

4.2.5 this关键字

this是当前对象,也可以看作是当前对象的别名(当前对象名)。

当通过一个对象调用一个成员方法时,系统就会将当前对象的别名传递到被调方法中,在这个被调方法中,当前对象名就是this.所以,this只能在成员方法中可见。

一个成员方法可以被这个类的多个对象调用,在某一时刻,哪一个对象调用这个方法,this就表示的是哪一个对象。

因为当局部变量与域变量重名时,在方法中只能访问到局部变量。如果想访问同名的域,就需要在域名(属性)前面加上this,表示是当前对象中的域,而不是局部变量。也就是,如果不存在同名问题,就无需使用this.

通俗来说,当我们在声明一个属性对应的方法时,通过形参给对应的属性赋值。如果形参名和属性名同名了,那么该如何在方法内区分这两个变量呢?

解决方案:使用this。具体来讲,使用this修饰的变量,表示的是属性。没有用this修饰的,表示的是形参。

//定义一个Person类

class Person{

//姓名

String name;

//年龄

int age;

}

//方法

public void setAge(int age){

this.age=age;

}

public int getAge(int age){

return this.age;

}

如形参和变量一样,不好区分,所以用this来区分,this修饰的变量,表示的是属性。没有用this修饰的,表示的是形参。

this可以调用的结构:成员变量、方法、构造器(构造方法)

一般情况:我们通过对象a调用方法,可以在方法内调用当前对象a的属性或其他方法。此时,我们可以在属性和其他方法前使用"this.",表示当前属性或方法所属的对象a。但是,一般情况下,我们都选择省略此"this."结构。

特殊情况:如果方法的形参与对象的属性同名了,我们必须使用"this ."进行区分。使用this.修饰的变量即为属性(或成员变量)﹐没有使用this.修饰的变量,即为局部变量。

4.2.6 参数传递

当一个方法定义时定义了形式参数,,则调用这个方法时必须给出实际参数。

1.基本数据类型作方法的参数 如果参数是基本数据类型,, 当这个方法被调用时,运行时系统会为形式参数开辟新的存储单元。所以,即使实际参数是一个变量,它与形参也不是同一个存储单元,形参的值改变了,实际参数的值不会改变。

class Point{

//域

int x,y;

}

.....

//基本数据类型作方法形参

private static void move( int x, int y){

x=x+2;

y=y+8;

}

2.对象名作方法的参数

因为对象名的值就是对象在内存中的地址 所以 当对象多作方法的参数时,是将对象的地址传递到被调方法中。这样,在被调用方法中的形参与主调方法中的实参指的是同一个对象。

class Point{

int x,y;

}

public class Person{

public static void main(String args[]){

Point p = new Point(2,-1);

......

move(p);

}

private static void move(Point p)//对象名作方法的参数

{

p.x=p.x+11;

p.y=p.y+24;

.....

}

3.数组名作方法的参数 数组名表示的是数组在内存中的起始地址。所以用数组名作方法的参数时,是将数组在内存中的起始地址传递到被调方法中,在被调用方法中就可以通过数组起始地址访问到数组中的每一个元素。

4.2.7 对象数组

如果想表示一个类的多个对象,可以用对象数组来表示,即数组中的每一个元素都是一个类的对象。

1.对象数组的定义

①先声明一个对象数组名。声明形式为:

类名 对象数组名 [ ];

②再创建对象数组,形式:

对象数组名 = new 类名[数组长度];

例如:平面上有很多点,可以用一个点类的对象数组表示:

Point p[ ] = new Point [10];

注意:创建对象数组与创建对象的不同之处。创建对象数组时在类名后用 “[ ]” 表示,创建对象时在构造方法后用 “()”表示。 创建对象数组后,相当于声明了若干个对象名,而对象并不真正存在,还需要为每个对象名创建对象。如刚创建的数组p,它有10个元素,相当于声明了10个Point类对象名,并不是真正的对象,还需要调用构造方法创建每一个对象。例如,让对象数组p中的每个元素都表示一个对象,可以使用循环:

for(int i=0;i

p[i]=new Point[];

}

2.对象数组初始化

在声明数组时就使数组中每一个元素表示一个对象,称为对象数组初始化。

对象数组初始化形式为:

类名 对象数组名 [ ] ={对象列表};

例如:

Point point[ ] = {new Point(-10,11),new Point(2,3)....};

“ 对象列表 ” 可以是新创建的对象,也可以是已经存在的对象。

4.2.8 static关键字关键字static用于修饰域和方法。用static修饰的域和方法称为类域和类方法,或称为静态域和静态方法 1.static修饰域 可以用关键字static修饰域。当用static修饰一个或多个域后,不论用这个类创建多少个对象,这些对象都有共同的一个或多个域,而不是每个对象独有的域。 通过将域声明为静态域,能够正确地表示出一个类的所有对象的共同属性(域)。 声明静态域的形式: 数据类型 static 域名[=初值]; 一次可以声明多个静态域,默认值(不初始化)为0。 因为静态域是一个类的所有对象的共同属性,所以又可以将静态域称为类域,可以通过类名直接访问。

2.static修饰方法

static修饰的方法又称为类方法或静态方法,可以通过对象名访问,更多的是通过类名访问。

定义类方法的主要目的是用类方法访问类域。定义类方法的形式为:

static 方法类型 方法名( [形参列表] ){

// ....方法体

}

static 方法类型 方法名( [形参列表] ){

// ....方法体

}

4.2.9 @Deprecated 注解

注解用于对程序或数据进行说明。@Deprecated是注解中的一种,表示它所注解的域或方法已经过时,不建议再使用。当然,使用也可以。使用时,将 “@Deprecated”放在被注解的域或方法的前面。