JAVA第6章类和对象

cbe89bcc5fef4b20a0e8225dbeecd10b.png
       在 Java 语言中,经常被提到的两个词是类与对象。实际上,可以将类看作是对象的载体,它定义了对象所具有的功能。学习 Java 语言必须掌握类与对象,这样可以从深层次去理解 Java 这种面向对象语言的开发理念,从而更好、更快地掌握 Java 编程思想与编程方式。本章将详细讲解类的各种方法以及对象,为了使初学者更容易入门,在讲解过程中列举了大量实例。

 

1d965989ca5342f3ba188433102e0470.png

 

6.1 面向对象概述

       在程序开发初期,人们使用结构化开发语言。随着软件的规模越来越庞大,结构化语言的弊端也逐渐暴露出来,开发周期越来越长,产品的质量也不尽如人意。这时人们开始将另一种开发思想引入程序中,即面向对象的开发思想。面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,通过了解这些对象具有哪些相应的属性以及展示这些对象的行为,以解决这些对象面临的一些实际问题。在程序开发中引入面向对象设计的概念,其实质上就是对现实世界中的对象进行建模操作。

6.1.1 对象

       现实世界中,随处可见的一种事物就是对象。对象是事物存在的实体,如人、书桌、计算机、高楼大厦等。人类解决问题的方式总是将复杂的事物简单化,于是就会思考这些对象都是由哪些部分组成的。通常都会将对象划分为两个部分,即静态部分与动态部分。顾名思义,静态部分就是不能动的部分,这个部分被称为“属性”,任何对象都会具备其自身属性,如一个人,其属性包括高矮、胖瘦、性别、年龄等。动态部分即对象可执行的动作,这部分称为“行为”,也是一个值得探讨的部分,同样对于一个人,其可以哭泣、微笑、说话、行走,这些都是这个人具备的行为。人类通过探讨对象的属性和观察对象的行为来了解对象。

       在计算机的世界中,面向对象程序设计的思想要以对象来思考问题,首先要将现实世界的实体抽象为对象,然后考虑这个对象具备的属性和行为。例如,现在面临一只大雁要从北方飞往南方这样一

个实际问题,试着以面向对象的思想来解决这一实际问题。步骤如下:

(1)从这一问题中抽象出对象,这里抽象出的对象为大雁。

  (2)识别这个对象的属性。对象具备的属性都是静态属性,如大雁有一对翅膀、黑色的羽毛等。这些

(3)识别这个对象的动态行为,即这只大雁可以进行的动作,如飞行、觅食等,这些行为都是这个对象基于其属性而具有的动作。

(4)识别出这个对象的属性和行为后,这个对象就被定义完成了。然后可以根据这只大雁具有的特性制定这只大雁从北方飞向南方的具体方案,以解决问题。

       究其本质,所有的大雁都具有以上属性和行为,可以将这些属性和行为封装起来,构成一个类,以描述大雁这类动物。由此可见,类实质上就是封装对象属性和行为的载体,而对象则是类抽象出来的一个实例。

6.1.2 类

       不能将一个事物描述成一类事物,如一只鸟不能称为鸟类。但如果要给某一类事物一个统称,需要用到类这个概念。

       类就是同一类事物的统称,如果将现实世界中的一个事物抽象成对象,类就是这类对象的统称。如鸟类、家禽类、人类等。类是构造对象时所依赖的规范,如一只鸟有一对翅膀,它可以用这对翅膀飞行,而基本上所有的鸟都具有“有翅膀”这个特性和飞行的技能,这样具有相同特性和行为的一类事物就称为类,类的思想就是这样产生的。已经描述过类与对象之间的关系,对象就是符合某个类的定义所产生出来的实例。更为恰当的描述是,类是世间事物的抽象称呼,而对象则是这个事物对应的实体。如果面临实际问题,通常需要实例化类对象来解决。例如,解决大雁南飞的问题,这里只能拿这只大雁来处理这个问题,而不能拿大雁类或鸟类来解决。

       类是封装对象的属性和行为的载体,反过来说,具有相同属性和行为的一类实体被称为类。例如,鸟类封装了所有鸟的共同属性和应具有的行为。

       定义完鸟类之后,可以根据这个类抽象出一个实体对象,最后通过实体对象来解决相关的实际问题。

       在 Java 语言中,类对象的行为是以方法的形式定义的,对象的属性是以成员变量的形式定义的,所以类包括对象的属性和方法。

6.1.3 封装

       面向对象程序设计具有以下特点:封装性、继承性和多态性。

       封装是面向对象编程的核心思想,将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。例如,用户使用计算机时,只需要使用手指敲击键盘就可以实现一些功能,无须知道计算机内部是如何工作的。即使知道计算机的工作原理,但在使用计算机时也并不完全依赖于计算机工作原理等细节。

       采用封装的思想保证了类内部数据结构的完整性,使用类的用户不能轻易地直接操作类的数据结构,只能执行类允许公开的数据。这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。

6.1.4 继承

       类与类之间同样具有关系,这种关系被称为关联。关联主要描述两个类之间的一般二元关系。例如,一个百货公司美与销售员类就是一个关联,学生类与教师类也是一个关联。两个类之间的关系有很多种,维承是关联中的一种。

       当处理一个问题时,可以将一些有用的类保留下来,在遇到同样的问题时拿来复用。假如这时需

要解决信鸽送信的问题,由于鸽子属于鸟类,具有与鸟类相同的属性和行为,便可以在创建信鸽类时将鸟类拿来复用,并且保留鸟类具有的属性和行为。不过,并不是所有的鸟都有送信的习惯,因此还需要再添加一些信鸽具有的独特属性及行为。鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共同具有的属性和行为的时间,这就是继承的基本思想,设计软件时,使用继承思想可以缩短软件开发的周期,复用那些已经定义好的类可以提高系统性能,减少系统在使用过程中出现错误的概率。

       继承性主要利用特定对象之间的共有属性。例如,平行四边形是四边形,正方形、矩形也都是四边形,平行四边形类与四边形类具有共同特性,就是拥有 4 个边,可以将平行四边形类看作四边形类的延伸,平行四边形类复用了四边形类的属性和行为,同时添加了平行四边形独有的属性和行为,如平行四边形的对边平行且扣等。这里可以将平行四边形类看作是从四边形类中继承的。在 Java 语言中,将类似于平行四边形类的类称为子类,将类似于四边形类的类称为父类或超类。值得注意的是,可以说平行四边形是特殊的四边形,但不能说四边形是平行四边形,也就是说子类的实例都是父类的实例,但不能说父类的实例是子类的实例。

       从 中可以看出,继承关系可以使用树形关系来表示,父类与子类存在一种层次关系。一个类处于继承体系中,它既可以是其他类的父类,为其他类提供属性和行为,也可以是其他类的子类,继承父类的属性和方法,如三角形类既是图形类的子类也是等边三角形类的父类。

6.1.5 多态

       在 6.1.4 节中介绍了继承、父类和子类,其实将父类对象应用于子类的特征就是多态。依然以图形类来说明多态,每个图形都拥有绘制自己的能力,这个能力可以看作是该类具有的行为,如果将子类的对象统一看作是父类的实例对象,这样当绘制图形时,简单地调用父类也就是图形类绘制图形的方法即可绘制任何图形,这就是多态最基本的思想。

       多态性允许以统一的风格编写程序,以处理种类繁多的已存在的类及相关类。该统一风格可以由父类来实现,根据父类统一风格的处理,可以实例化子类的对象。由于整个事件的处理都只依赖子父类的方法,所以日后只要维护和调整父类的方法即可,这样就降低了维护的难度,节省了时间。   

       提到多态,就不得不提抽象类和接口,因为多态的实现并不依赖于具体类,而是依赖于抽象类和接口。

       再回到绘制图形的实例上来。图形类作为所有图形的父类,具有绘制图形的能力,这个方法可以称为“绘制图形”,但如果要执行这个“绘制图形”的命令,没有人知道应该画什么样的图形,并且如果要在图形类中抽象出一个图形对象,没有人能说清这个图形究竟是什么图形,所以使用“抽象”这个词来描述图形类比较恰当。在 Java 语言中,称这样的类为抽象类,抽象类不能实例化对象。在多态的机制中,父类通常会被定义为抽象类,在抽象类中给出一个方法的标准,而不给出实现的具体流程。实质上这个方法也是抽象的,如图形类中的“绘制图形”方法只提供一个可以绘制图形的标准,并没有提供具体绘制图形的流程,因为没有人知道究竟需要绘制什么形状的图形。

       在多态的机制中,比抽象类更方便的方式是将抽象类定义为接口。由抽象方法组成的集合就是接口。接口的概念在现实中也极为常见,如从不同的五金商店买来螺丝帽和螺丝钉,螺丝帽很轻松地就可以拧在螺丝钉上,可能螺丝帽和螺丝钉的厂家不同,但这两个物品可以轻易地组合在一起,这是因为生产螺丝帽和螺丝钉的厂家都遵循着统一的标准,这个统一的标准在 Java 中就是接口。依然拿“绘制图形”来说明,可以将“绘制图形”作为一个接口的抽象方法,然后使图形类实现这个接口,同时实现“绘制图形”这个抽象方法,当三角形类需要绘制时,就可以继承图形类,重写其中的“绘制图形”方法,并改写这个方法为“绘制三角形”,这样就可以通过这个标准绘制不同的图形。

6.2 类

       在 6.1.2 节中已经讲解过类是封装对象的属性和行为的载体,而在 Java 语言中对象的属性以成员变量的形式存在,对象的方法以成员方法的形式存在。本节将讲解类在 Java 语言中是如何定义的。

6.2.1 成员变量

       在 Java 中,对象的属性也称为成员变量,成员变量可以是任意类型,整个类中均是成员变量作用范围。下面通过一个实例来演示成员变量在类中所处的位置。

 

【例 6.1】为书添加书名属性(实例位置:资源包\TM\sl\6\1)

创建一个 Book 类,在类中设置一个 name 属性,并为该属性编写 Getter/Setter 方法。

5e73de7d162944d0882a8a9adef2afec.png

       在上面这个实例中可以看到,在 Java 语言中需要使用 class 关键字来定义类,Book 是类的名称。同时在 Book 类中定义了一个成员变量,成员变量的类型为 String 类型。其实成员变量就是普通的变量,可以为它设置初始值,也可以不设置初始值。如果不设置初始值,则会有默认值。读者应该注意到成员变量 name 前面有一个 private 关键字,它用来定义一个私有成员。

6.2.2 成员方法


        在 Java 语言中,使用成员方法对应干类对象的行为,以 Book 类为例,它包含 getName()和 seName()两个方法,这两个成员方法分别为获取图书名称和设置图书名称的方法。
定义成员方法的语法格式如下:

 

权限修饰符 返回值类型 方法名(参数类型 参数名){
...                                 //方法体
return 返回值;


       一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量,同时成员方法有返回值和不返回任何值的选择,如果方法需要返回值,可以在方法体中使用 return 关键字,使用这个关键字后,方法的执行将被终止。

注意
       要使 Java 代码中的成员方法无返回值,可以使用 void 关键宇表示。


       成员方法的返回值可以是计算结果,也可以是其他想要的数值和对象,返回值类型要与方法返回
的值类型一致。
       在成员方法中可以调用其他成员方法和类成员变量,如在例 6.1 的 getName()方法中就调用了setName()方法将图书名称赋予一个值。同时,在成员方法中可以定义一个变量,这个变量为局部变
量(局部变量的内容将在 6.2.4 节中进行讲解)。


说明
       如果一个方法中含有与成员变量同名的局部变量,则方法中对这个变量的访问以局部变量进行。
类的成员变量和成员方法也可以统称为类成员。


6.2.3 权限修饰符


       Java 中的权限修饰符主要包括 private、public 和 protected,这些修饰符控制着对类和类的成员变量以及成员方法的访问。如果一个类的成员变量或成员方法被修饰为 private,则该成员变量只能在本类中被使用,在子类中是不可见的,并且对其他包的类也是不可见的。如果将类的成员变量和成员方法的访问权限设置为 public,那么除了可以在本类使用这些数据,还可以在子类和其他包的类中使用。如果一个类的访问权限被设置为 private,这个类将隐藏其内的所有数据,以免用户直接访问它。如果需要使类中的数据被子类或其他包中的类使用,可以将这个类设置为 public 访问权限。如果一个类使用protected 修饰符,那么只有本包内的该类的子类或其他类可以访问此类中的成员变量和成员方法。

       这么看来,public 和 protected 修饰的类可以由子类访问,如果子类和父类不在同一包中,那么只有修饰符为 public的类可以被子类进行访问。如果父类不允许通过继承产生的子类访问它的成员变量,那么必须使用 private 声明父类的这个成员变量。表 6.1 中描述了 private、protected 和 public 修饰符的修饰权限。

 

表 6.1 Java 语言中的修饰符权限

 

注意

       当声明类时不使用 public、protected 和 private 修饰符设置类的权限,则这个类预设为包存取范围,即只有一个包中的类可以访问这个类的成员变量或成员方法。

 

例如,在项目中的 com.mr 包下创建 AnyClass 类,该类使用默认的访问权限。

package com.mr;

class AnyClass {

public void doString(){

… //方法体

}

}

       在上述代码中,由于类的修饰符为默认修饰符,即只有一个包内的其他类和子类可以对该类进行访问,而 AnyClass 类中的 doStringO方法却又被设置为 publie 访问权限,即使这样,doStingO方法的访问权限依然与 AnyClass 类的访问权限相同。

6.2.4 局部变量

       在 6.2.2 节中已经讲述过成员方法,如果在成员方法内定义一个变量,那么这个变量被称为局部变量。

       实际上,方法中的形参也可作为一个局部变量。例如,在例6.1的 Book类中定义stNlame(String name)方法,String name 这个形参就被看作是局部变量。

       局部变量是在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。

 

【例 6.2】交换两个整数的值(实例位置:资源包\TM\sl\62)

       在 ChangeDemo 类中创建静态的 exchange()方法,该方法可以将数组参数 arr的前两个元素值互换,通过在方法中定义一个保存临时数据的局部变量 tmp,利用 tmp 交换两个元素的值。

3e0f2e27302845d090df800a98bf3900.png

 

6.2.5 局部变量的有效范围

       可以将局部变量的有效范围称为变量的作用域,局部变量的有效范围从该变量的声明开始到该变量的结束为止。图 6.7 描述了局部变量的作用范围。

       在相互不嵌套的作用域中可以同时声明两个名称和类型相同的局部变量。

       但是在相就眼套的区域中不可以这样声明,如果将局部变量讨在方法体的 for 据环中再次定义国评喜将会限错。

注意

       在作用范围外使用局部变量是一个常见的错误,因为在作用范围外没有声明局部变量的代码。

6.2.6 this 关键字

       this 关键字用于表示本类当前的对象,当前对象不是某个 new 出来的实体对象,而是当前正在编辑的类。this 关键字只能在本类中使用。

       例如,例 6.1 中图书类的 setName()方法代码如下:

public void setName(String name){

//定义一个 setName()方法

this. name=name;

//将参数值赋予类中的成员变量

}

       在上述代码中可以看到,成员变量与 setName(方法中的形式参数的名称相同,都为 name,那么该如何在类中区分使用的是哪一个变量呢?在 Java 语言中,规定使用 this 关键字来代表本类对象的引用,this 关键字被隐式地用于引用对象的成员变量和方法,如在上述代码中,this.name 指的就是 Book类中的name 成员变量,而this.name = name 语句中的第二个name则指的是形参name.实质上,setName()方法实现的功能就是将形参 name 的值赋予成员变量 name。

       在这里读者明白了 this 可以调用成员变量和成员方法,但 Java 语言中最常规的调用方式是使用“对象.成员变量”或“对象.成员方法”进行调用。

       既然 this 关键字和对象都可以调用成员变量和成员方法,那么 this 关键字与对象之间具有怎样的关系呢?事实上,this 引用的就是本类的一个对象。在局部变量或方法参数覆盖了成员变量时,如上面代码的情况,就要添加 this 关键字明确引用的是类成员还是局部变量或方法参数。

       如果省略 this 关键字直接写成 name = name,那只是把参数 name 赋值给参数变量本身而已,成员变量 name 的值没有改变,因为参数 name 在方法的作用域中覆盖了成员变量 name。

       其实,this 除了可以调用成员变量或成员方法,还可以作为方法的返回值。例如,返回图书类本类的对象,可以写成下面这种形式:

public Book getBook(){

return this;

//返回 Book 类的本类对象

}

6.3 类的构造方法

       在类中,除成员方法外,还存在一种特殊类型的方法,那就是构造方法。构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造

方法。

构造方法的特点如下:

       构造方法没有返回值。

       构造方法的名称要与本类的名称相同。

注意

       在定义构造方法时,构造方法没有返回值,但这与普通没有返回值的方法不同,普通没有返回值的方法使用 public void methodEx(这种形式进行定义,但构造方法并不需要使用 void 关键字进行修饰。

构造方法的定义语法格式如下:

public Book(){

//构造方法体

}

      public:构造方法修饰符。

      Book:构造方法的名称。

       在构造方法中可以为成员变量赋值,这样当实例化一个本类对象时,相应的成员变量也将被初始化。如果类中没有明确定义构造方法,编译器会自动创建一个不带参数的默认构造方法。

注意

       如果在类中定义的构造方法都不是无参的构造方法,那么编译器也不会为类设置一个默认的无参构造方法,当试图调用无参构造方法实例化一个对象时,编译器会报错。所以,只有在类中没有定义任何构造方法时,编译器才会在该类中自动创建一个不带参数的构造方法。

       在 6.2.6 节中介绍过 this关键字,了解了 this可以调用类的成员变量和成员方法,事实上this还可以调用类中的构造方法,看下面的实例。

【例 6.3】“构造”鸡蛋灌饼(实创位置:资源包\TM\sl\6\3)

       当顾客购买鸡蛋灌饼时,如果要求加两个蛋。店家就给饼加两个蛋;不要求时,店家会默认给饼加一个蛋。创建鸡强灌针类(EegCake 类),使用this 关键字,在无参构造方法中调用有参构造方法。实现上述加蛋过程。代码如下:

979aaedea2be4c7fbb153b53ac594db3.png 

6.4 静态变量和静态方法

在介绍静态变量和静态方法之前,首先需要介绍 statie 关键字,因为由 static 修饰的变量和方法被称为静态变量和静态方法。

       有时,在处理问题时会需要两个类在同一个内存区域共享一个数据。例如,在球类中使用圆周率 PI 这个值,可能除了本类需要这个值,在另外一个圆类中也需要使用。这时没有必要在两个类中同时建 PI因为这样系统会将这两个不在同一个类中定义的静态值分配到不同的内存空间中。为了解决这个问题,可以将 PI 设置为静态的。PI 在内存中被共享布局。

       被声明为 static 的变量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和“.”运算符调用静态成员。语法如下:

类名,静态类成员

【例 6.4】创建并调用静态属性和静态变量(实例位置:资源包\TM\sl\6\4)

创建 StaticDemo 类,在类中使用 static 关键字定义一个属性和一个方法,并在主方法中调用。

cabd1a64add64a68a0f70d2583a23227.png

 

注意

       虽然静态成员也可以使用“对象.静态成员”的形式进行调用,但通常不建议用这样的形式,因为这样容易混淆静态成员和非静态成员。

       静态变量与静态方法的作用通常是为了提供共享数据或方法,如数学计算公式等。尽管使用这种方式调用静态成员比较方便,但静态成员同样遵循着 public、private 和 protected 修饰符的约束。

【例 6.5】统计顾客总人数(实例位置:资源包\TM\sl\6\5)

       Cust 类中创建一个静态整数类型属性 count,在构造方法中让 count 自增。

75724529a76a4ba9866e1d5a55fd6168.png

 

       从这个结果可以看出,因为count 是用 staic 修饰的,对于所有顾客来说这是一个共享的属性,每创建一个顾客,count 这个属性都会加 1,所以最后 count统计出来的就是顾客的总人数。

       如果在执行类时,希望先执行类的初始化动作,可以使用 static 定义一个静态区域,这块区域被称为静态代码块。当类文件被执行时,会首先执行 sttio 块中的程序,并且只会执行一次。静态代码块的语法如下:

public class example {

static{

…//可以在这里写初始化的代码

}

}

最后总结以下使用 static 关键字要注意的几点:

在静态方法中不可以使用 this 关键字。

在静态方法中不可以直接调用非静态方法。

局部变量不可以使用 static 关键字声明。

主方法必须用 static 声明。

只有内部类可以使用 statie 关键字声明。

6.5 类的主方法

        主方法是类的入口点,它定义了程序从何处开始。主方法提供对程序流向的控制,Java 编译器通过主方法来执行程序。主方法的语法如下:

public static void main(Stringl args){

...//方法体

}

在主方法的定义中可以看到其具有以下特性;

       主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。

       主方法没有返回值。

       主方法的形参为数组。其中,args[0]~args[n]分别代表程序的第一个参数到第n个参数,可以使用 args.length 获取参数的个数。

【例 6.6】读取主方法的参数值(实例位置:资源包\TM\sI\6\6)

       在项目中创建 TestMain 类,在主方法中编写以下代码,并在 Eclipse 中设置程序参数。

41eccdae51f44fb1a696796aec3be12e.png

 

       运行代码前,先要在 Eclipse 中设置运行参数,步骤如下:

       (1)在 Eclipse 中的 MainDemjava 文件上单击鼠标右键,在弹出的快捷菜单中选择“运行方式”/“运行配置”(英文版为 Run As / Run Configrations),弹出“运行配置”(Run Configrations)对话框。

      (2)在“运行配置”对话框中选择“自变量”(Arguments)选项卡,在“项目”(Program arguments)汇本框中输入相应的参数,每个参数间按 Enter 键隔开。具体设置如图 6.11 所示。

    (3)单击“运行”按钮,查看控制台运行结果,结果如下:

参数 1

参数2

       如果不按照以上步骤操作,直接运行源码,则不会输出任何结果。

6.6 对象

       Java 是一门面向对象的程序设计语言,对象是由类实例化而来的,所有问题都通过对象来处理。对象可以通过操作类的属性和方法来解决相应的问题,所以了解对象的产生、操作和消亡是十分必要的。本节就来讲解对象在 Java 语言中的应用。

6.6.1 对象的创建

       在 6.1 节中曾经讲解过对象,对象可以认为是在一类事物中抽象出某一个特例,可以通过这个特例来处理这类事物出现的问题。在 Java 语言中,通过 new 操作符来创建对象。前文在讲解构造方法时介绍过,每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程。准确地说。可设在 Java 语言中使用 new 操作特调用构造方法创速对象。请法如下。

Test test = new Test();

Test test = new Tes他("a");

       test 对象被创建出来时,就是一个对象的引用,这个引用在内存中为对象分配了存储空间。6.3节中介绍过,可以在构造方法中初始化成员变量,当创建对象时,自动调用构造方法。也就是说,在Java语言中,初始化与创建是被捆绑在一起的。

       每个对象都是相互独立的,在内存中占据独立的内 存地址,并且每个对象都具有自己的生命周期,当一个对象的生命周期结束时,对象就变成垃圾,由 Java 虚拟机自带的垃圾回收机制处理,不能再被使用。

注意

      在Java 语言中,对象和实例事实上可以通用。

【例 6.7】创建人类并创建其对象(实例位置:资源包NTMsl\6\7)

       创建人类(Pcople 类),类中有名字、年龄和性别 3 个属性,并为 People 类创建有参和无参两种构造方法。以人类为模板,创建两个对象,分别为23 岁名叫 tom 的小伙子、19 岁名叫 lily 的小姑娘。

3b8a3f748e594358abe01b944a57d48f.png

6.6.2 访问对象的属性和行为

        用户使用nceW操作符创建一个对象后,可以使用“对象,类成员”来获取对象的属性和行为。前文已经提到过,对象的属性和行为在类中是通过类的成员变量和成员方法的形式来表示的,所以当对象获取类成员时,也相应地获取了对象的属性和行为。

【例 6.8】描述狗的特征(实例位置:资源包\TM\sl\6\8)

       在 Dog 类中创建名字、颜色和声音 3 个属性,再创建一个“叫”的方法。以 Dog 类为模板创建两只狗,一只是白色且会汪汪汪叫的毛毛,一只是灰色且会嗷呜叫的灰灰。

4a456bc81ea944258e350528bab1c6aa.png

 

6.6.3 对象的引用

在Java 语言中,尽管一切都可以看作对象,但真正的操作标识符实质上是一个引用,那么引用在Java 中是如何体现的呢?语法如下:

类名对象的引用变量

        例如,一个 People 类的引用可以使用以下代码:

People tom;

       通常一个引用不一定需要有一个对象相关联。引用与对象相关联的语法如下:

People tom = now People();

       实际上真正的对象是“new People()”这段代码。为了方便开发者保存、调用对象,于是创建了一个People 类型、名叫 tom 的引用变量。实际上,tom 只是一段内存地址,用于标记“new People(”对象在内存中的位置。因为内存地址又长又乱,很难让人记住,所以 Java 语言利用引用变量帮开发者标记内存地址。开发者只要记住引用变量的名字,就能够在内存里找到对象数据。简单来说,tom 是 newPeople()的“代理人”。

        既然 tom 是 new PeopleO的“代理人”,那么“new People()”对象能做的事,tom 也能做。例如,下面这行代码:

new People().getClass();

等价于:

[People tom = new People();

tom.getClass();

6.6.4 对象的销毁

       每个对象都有生命周期,当对象的生命周期结束时,分配给该对象的内存地址需要被回收。在其他语言中,需要用户手动回收废弃的对象。Java 拥有一套完整的垃圾回收机制,用户不必担心废弃的对象占用内存,垃圾回收器会自动回收无用却占用内存的资源。

       在学习垃圾回收机制之前,读者首先需要了解何种对象会被 Java 虚拟机视为“垃圾”。主要包括以下两种情况:

       对象引用超过其作用范围,这个对象将被视为垃圾。

       对象赋值为null。

       虽然 JAVA的圾回收机制已经很完善,但垃圾回收器只能回收那些的 new 操作符创建的对象。某些对象不是通过 nW 操作符在内存中获取存储空同的,这种对象无法被垃圾回收机制所识别。在 Java中,提供了一个 fmize0方法。这个方法是 Oboct 类的方法,它被声明为 proteeted,用户可以在自己的类中定义这个力法。如果用户在赛中定义了 finalize0方法,在垃圾回收时会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。

说明

需要明确的是,垃圾园收成 finlin0方法并不保证一定会发生。如果 Java虚拟机内存损耗待尽,它将不会执行垃圾回收处理。

       由于垃圾回收不受人为控制,具体执行时间也不确定,所以 fhnalize0方法也就无法执行。为此,Java提供了 SysitemgeV)方法来强制启动垃圾回收器,这与给 120 打电话通知医院来救护病人的道理—样,主动告知垃圾回收器来进行清理。

 

 

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值