900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > Java面向对象-01-类和对象

Java面向对象-01-类和对象

时间:2024-01-27 09:44:00

相关推荐

Java面向对象-01-类和对象

一、面向对象概述

一、面向对象概述

在程序开发初期人们使用结构化开发语言,但是随着时间的流逝,软件的规模越来越庞大,结构化语言的弊端也逐渐暴露出来,开发周期被无休止的拖延,产品的质量也不尽如人意,人们终于发现结构化语言已经不再适合当前的软件开发。这时人们开始将另一种开发思想引入程序中,那就是面向对象的开发思想。面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,同时了解这些对象具有相应的属性以及展示这些对象的行为,以解决这些对象面临的一些实际问题,这样就在程序开发中引入了面向对象设计的概念。在面向对象程序设计里,将数据和处理数据的方法紧密的结合在一起,形成类,再将类实例化,就形成了对象。在面向对象的世界中,你不再需要考虑数据结构和功能函数,只要关注对象就可以了。

对象就是客观世界中存在的人、事和物体等实体。在现实世界中,对象随处可见,例如,路边生长的树、天上飞的鸟、水里游的鱼和路上跑的车等。不过这里说的树、鸟、鱼和车都是对同一类事物的总称,这就是面向对象中的类(class)。这时读者可能要问,那么对象和类之间的关系是什么呢?对象就是符合某种类定义所产生出来的实例(instance),虽然在日常生活中我们习惯用类名称呼这些对象,但是实际上看到的还是对象的实例,而不是一个类。例如,你看见树上落着一只鸟,这里的“鸟”虽然是一个类名,但实际上你看见的是鸟类的一个实例对象,而不是鸟类。由此可见,类只是个抽象的称呼,而对象则是与现实生活中的事物相对应的实体。类与对象的关系如下图所示:

在现实生活中,只是使用类或对象并不能很好的描述一个事物,例如,李明对妈妈说我今天看见一只鸟,这时妈妈就不会知道李明说的鸟是什么样子的。但是如果李明说看见一只绿色的会说话的鸟,这时妈妈就可以想象到这只鸟是什么样的。这里说的绿色是指对象的属性,而会说话则是指对象的方法。由此可见,对象还具有属性和方法。在面向对象程序设计中,使用属性来描述对象的状态,使用方法来处理对象的行为。

二、对象

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

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

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

(2)然后识别这个对象的属性,对象具备的属性都是静态属性,例如大雁具有一对翅膀,一双脚等,这些属性如下图所示:

(3)接着是识别这个对象的动态行为,即这只大雁可以进行的动作,例如飞行、觅食等,这些行为都是因为这个对象基于这些对象属性而具有的动作,这些行为如图下所示:

(4)识别出这些对象的属性和行为后,这个对象就被定义完成,然后可以根据这只大雁具有的特性制定这只大雁要从北方飞向南方的具体方案以解决问题。实质上究其本质,所有的大雁都具有以上的属性和行为,可以将这些属性和行为封装起来以描述大雁这类动物。由此可见,类实质上就是封装对象属性和行为的载体,而对象则是类抽象出来的一个实例,二者之间的关系如图下所示:

三、类

不能将所谓的一个事物描述成一类事物,比如,一只鸟不能称为鸟类,如果需要对同一类事物统称就不得不说明类这个概念。

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

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

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

四、封装

面向对象程序设计具有以下特点:

·封装性

·继承性

·多态性

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

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

使用类实现封装特性如图下所示:

五、继承

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

当处理一个问题时,可以将一些有用的类保留下来,当遇到同样问题时拿来复用,假如这时需要解决信鸽送信的问题,由于鸽子属于鸟类,鸽子具有鸟类相同的属性和行为,但并不是所有的鸟都有送信的习惯,但可以在创建信鸽类时将鸟类拿来复用,并且保留鸟类具有的属性和行为,然后再添加一些信鸽独特具有的属性以及行为,鸽子类保留了鸟类的属性和行为,这样就节省了定义鸟和鸽子共同具有的属性和行为的时间,这就是继承的基本思想。可见软件的代码使用继承思想可以缩短软件开发的时间,复用那些已经定义好的类可以提高系统性能,减少系统在使用过程中出现错误的几率。

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

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

六、多态

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

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

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

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

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

二、类

一、类的定义

类是用来定义一组对象共同具有的状态和行为的模板。而对象是现实世界中个体或事物的抽象表示,并封装了它们的属性和行为,例如一个员工可以表示为一个对象,它有姓名、性别、年龄等属性,同时也具有吃、喝、走、跑、说话等行为。这些属性和行为都是“人类”所具有的,也就是说类声明了这些共同的特性,对象(也就是类的实例)在使用之前,必须定义该对象的类,知道了对象的类型,才能够访问它的属性和行为。

在Java语言中,对象的行为被定义成类的方法,对象的属性定义为类成员变量。所以一个类包括对象的属性和行为。它由class关键字声明,其语法格式如下:

class className{成员变量……成员方法……}

其中className是要定义的类的名称,在类体中可以定义多个成员变量和成员方法,在之前的实例中,经常使用的是main()方法,这就是一种特殊的成员方法,因为它作为程序执行的入口方法,用于执行程序。

定义一个Fruit类,该类拥有public访问权限,即该类可以被它所在包之外的其他类访问或引用。

public class Fruit {}

定义一个水果类Fruit,在该类中定义了一个表示颜色的属性color、一个表示种植的方法plant()、一个表示生长的方法grow()和一个表示收获的方法harvest()。

/*例 定义一个水果类Fruit,在该类中定义了一个表示颜色的属性color、一个表示种植的方法plant()、一个表示生长的方法grow()和一个表示收获的方法harvest()。*/public class Fruit {//水果类//定义颜色成员变量String color = "";//定义种植成员方法public void plant(){System.out.println("种子正在种植……");}//定义生长成员方法public void grow(){System.out.println("种子生长中……");}//定义收货成员方法public void harvest(){System.out.println("水果获取中……");}}

说明:类名的首字母通常为大写。

二、成员变量

成员变量是在类体中定义的变量,即全局变量,成员变量用于定义对象的状态。例如Student类有name、age、sex等成员变量分别表示姓名、年龄、性别等状态。

/*例如Student类有name、age、sex等成员变量分别表示姓名、年龄、性别等状态。*/public class Student {public String name; //姓名public int age; //年龄public String sex; //性别}

说明:成员变量必须直接定义在类体中,如果定义在其他方法或代码块中,就会成为局部变量,而不是成员变量。

成员变量是给对象使用的,每个对象被创建以后,都会有属于自己的属性,即成员变量。通过修改这些属性,从而改变对象的某个状态。如下图所示,不同的实例对象设置了不同的属性。

三、成员方法

成员方法是对象行为的描述。每个方法都是由复合语句描述相应的行为。定义成员方法的语法格式如下:

语法:

修饰符 返回值类型 方法名(形参表){...//方法体return 返回值;}

修饰符:可以是public、private、protected以及static、final等。修饰符是可选的语法部分。

返回值类型:如果方法需要返回值,必须在这里声明方法的返回值类型,可以使基本数据类型(int、short、double、boolean等),也可以是对象类型(例如数组、字符串等)

方法名:这是必须的方法定义部分,程序将通过该名称调用这个方法。

形参表:这是可选部分,说明方法被调用时,应该向它传递的数据。

形参表由1到多个形式参数构成,当方法有多个形式参数时,参数之间使用“,”逗号分割;如果方法没有参数,可以省略“形参表”部分。

例如:

public void SaveBookInfo(String bookName,String publishing,String writer){//方法体}

这段代码定义了saveBookInfo()方法实现图书信息的保存,最简单的图书信息也要有书名、出版社、作者等信息,所以该方法的形参表定义了bookName、publishing和writer参数。

说明:成员变量和成员方法统称为类成员。

四、权限修饰符

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

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

package com;class AnyDemo {public void doString(){//方法体}}

在上述代码中,由于该类采用默认的修饰符,即只有一个包内的其他类和子类可以对该类进行访问,而AnyClass类中的doString()方法却又被设置为public访问权限,即使这样,doString()方法的访问权限依然与AnyClass类的访问权限相同,因为Java语言规定,类的权限设定会约束类成员上的权限设定,所以上述代码等同于下面的代码。

本例等同于上例代码

package com;class AnyDemo {void doString(){//方法体}}

五、局部变量

如果在成员方法内定义一个变量,那么这个变量被称为局部变量,局部变量只在定义它的方法内有效。

比如定义一个Book类,具体代码如下:

public class Book {String name = "";//定义一个getName()方法public String getName(){//局部变量int id = 0;//调用类中其他方法setName(" HelloWorld ");return id + this.name;}public void setName(String name) {this.name = name;}}

在上面的代码中,getName()方法的id变量即为局部变量,实际上方法中的形参也可作为一个局部变量,例如setName()方法中的name,这个形参也被看作是局部变量。

局部变量是在方法被执行时创建,在方法执行结束时被销毁,局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。例如,上面的代码中,如果将局部变量id的初始值去掉,编译器将出现错误。

六、局部变量的有效范围

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

在相互不嵌套的作用域中可以同时声明两个名称、类型相同的局部变量,例如下图所示:

但是在相互嵌套的区域中不可以这样声明,如果将局部变量id值在方法体的for循环中再次定义,编译器将会报错,如下图所示。

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

七、this关键字

在项目中创建一个类文件,该类中定义了setName(),并将方法的参数值赋予类中的成员变量。

private 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引用就是对一个对象的引用。

在setName()方法体中也可以使用name = name这种形式,可以在引用成员变量时省略this关键字,其结果与使用this关键字是一致的。既然使用this与没有使用this的效果相同,那么为什么要使用this关键字,其实this除了可以调用成员变量或成员方法之外,还可以作为方法的返回值,代码如下:

在项目中创建一个类文件,该类中定义Book类型的方法,并通过this关键字进行返回。

public Book getBook(){return this; //返回Book类引用}

在getBook()方法中,方法的返回值为Book类型,所以方法体中使用return this这种形式将Book类型的对象进行返回。

三、类的构造方法

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

构造方法的特点如下:

·声明构造方法没有返回值类型。

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

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

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

语法:

public 类名(参数列表){//构造方法体}

public:构造方法修饰符。

类名:构造方法的名称,它必须和类名相同。

参数列表:可选参数,可以定义多个参数为构造方法传参,也可以不定义参数,使用没有任何参数的默认构造方法。

说明:如果类中没有明确定义任何构造方法,则编译器会自动创建一个不带参数的默认构造方法。

在构造方法中可以完成变量赋值、连接数据库等初始化工作,这样当实例化一个本类的对象时,相应初始化工作就自动完成了。

和成员方法一样,构造方法也可以重载,定义参数列表不同的多个构造方法可以创建并初始化不同的对象。例如Student类的构造方法可以根据传递的姓名、性别、年龄等不同参数的值,来创建不同的学生对象,这些参数在程序中可能来源于现实世界,类似招生人员登记学生信息时,招生人员就是构造方法,每个学生都是一个对象,而它们的信息就是构造方法的参数。如下图所示。你甚至可以为Student类添加指纹、血型等属性来进一步区别每个学生对象,但是那基本上超出了程序的业务范围。所以,在定义类的时候,要选择合适的属性和行为进行定义

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

定义Student类,在类中定义姓名、年龄和性别3个成员变量,再定义3个不同参数的构造方法,其中有一个是无参数的默认的构造方法。然后定义sayMyInfo()方法输出自己的信息。

/*** 例 定义Student类,在类中定义姓名、年龄和性别3个成员变量,再定义3个不同参数的构造方法,* 其中有一个是无参数的默认的构造方法。然后定义sayMyInfo()方法输出自己的信息。*/public class Student {private String name;//姓名private String sex;//性别private int age;//年龄/*** 默认构造方法*/public Student(){name = "未登记";sex = "未登记";age = 0;}/*** 带姓名参数的构造方法* @param name 学生的姓名*/public Student(String name){this.name = name;}/*** 初始化所有成员变量的构造方法* @param name 学生的姓名* @param sex 学生的性别* @param age 学生的年龄*/public Student(String name,String sex,int age){this(name);this.sex = sex;this.age = age;}/*** 输出学生自己的信息的方法*/public void SayMyInfo(){System.out.println("以下是本人的个人信息:");System.out.println("姓名:" + name);System.out.println("性别:" + sex);System.out.println("年龄:" + age);System.out.println("******************************");}public static void main(String[] args) {Student student1 = new Student("张三","男",13);Student student2 = new Student("小芳");Student student3 = new Student();student1.SayMyInfo();student2.SayMyInfo();student3.SayMyInfo();}}

运行结果如下图所示:

本实例定义了两个参数列表不同的构造方法,还有一个无参数的默认构造方法。实例中跟别使用这3个构造方法创建了对象,然后调用了每个对象的SayMyInfo()方法输出自己的信息,从运行结果可以看出不同的构造方法完成了不同程度的初始化,在实际程序开发中,可以利用构造方法完成更加灵活的初始化操作。例如加载数据库驱动类、根据构造参数连接数据库等。

四、静态变量、常量和方法

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

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

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

语法:

类名.静态类成员

在项目中创建Calculate类,该类中的主方法调用静态成员并在控制台中输出。

package com.sr1;//定义类包/*** 例 在项目中创建Calculate类,该类中的主方法调用静态成员并在控制台中输出。*/public class Calculate {//创建类static final double PI = 3.141592654;//定义静态常量static int id;//定义静态变量public static void method() {//在类中定义静态方法System.out.println("这是由静态方法输出的");id = 29;}public static void main(String[] args) {System.out.println(Calculate.PI);//调用静态常量System.out.println("调用静态方法前id的值:" + Calculate.id);//调用静态变量Calculate.method();//调用静态方法System.out.println("调用静态方法后id的值:" + Calculate.id);//调用静态变量}}

运行结果如下图所示:

在以上实例中设置了3个静态成员,分别为常量、变量和方法,然后在main()方法中分别调用这3个静态成员,直接使用“类名.静态成员”形式进行调用即可。

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

静态数据与静态方法的作用通常是为了提供共享数据或方法,比如数据计算公式等,以static声明并实现,这样当需要使用时,直接使用类名调用这些静态成员即可。尽管使用这种方式调用静态成员比较方便,但静态成员同样遵循着public、private、protected修饰符的约束。

在Calculate类中添加一个非静态方法method1()和一个静态方法method2(),并且在method2()中调用method1(),以及在return语句中使用this关键字。

在idea中输入上述代码后,编译器会发生错误,这是因为method2()方法为一个静态方法,而在其方法体中调用了非静态方法和this关键字。在Java语言中对静态方法有以下两点规定。

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

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

注意:在Java中规定不能将方法体内的局部变量声明为static的。例如下面的代码就是错误的。

技巧:如果在执行类时,希望先执行类的初始化动作,可以使用static定义一个静态区域,例如:

当这段代码被执行时,首先执行static块中的程序,并且只会执行一次。

五、类的主方法

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

public static void main(String[] args){//方法体}

从主方法的定义中可以看到主方法具有如下几点特性:

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

·主方法没有返回值。

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

六、对象

一、对象的创建

一个汽车的设计图纸永远不能用来驾驶出行,你必须用它生产出真正的汽车才能使用。这个汽车的设计图纸可以比作我们之前设计的类,而真正的汽车(例如白色轿车)可以比作是对象,只有对象才能被程序使用,而且同一类型的对象还有不同的属性,例如颜色、高度、速度等,另外,对象还可以执行类设计的方法,即对象的行为,例如开车、换挡、加油、转向和刹车等。

创建类的实例对象需要使用new语句,声明并创建对象的语法格式如下。

语法:

类名 对象名 = new 类构造方法();

类名:这是要创建实例对象的类的名称。

对象名:它可以看作是一个变量,这个变量名就是创建的实例对象的名称。

构造方法:是类创建对象时必须执行的方法,用于构造一个新的对象并初始化对象属性。

例如:

String name = new String("一个新的字符串对象");

这句代码声明了字符串变量name,并且使用new语句创建了字符串对象,String是一个特殊的类,它可以使用双引号的字面量创建对象,也可以使用new语句创建,但是我们自己写的类,只能使用new语句创建。

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

在项目中创建CreateObject类,并在该类的主方法中创建该类的对象。

/*** 例 在项目中创建CreateObject类,并在该类的主方法中创建该类的对象。*/public class CreateObject {public CreateObject(){//构造方法System.out.println("在CreateObject类的主方法中创建对象");}public static void main(String[] args) {new CreateObject();}}

运行结果如下图所示:

在上述实例的主方法中使用new操作符创建对象,在创建对象的同时,自动调用构造方法中的代码。

二、访问对象的属性和行为

在Java中,创建对象以后,可以访问对象的属性,即成员变量。访问对象属性需要使用“.”操作符。

语法:

对象名.属性对象名.成员方法名()

在对象名后面使用“.”操作符连接对象的属性或方法。

例如:

String carColor = whiteCar.color;whiteCar.color = "黑色";whiteCar.run();

第一条语句把whiteCar对象的颜色赋值给了carColor变量,第二条语句把whiteCar对象的color颜色属性赋值为“黑色”,第三条语句调用whiteCar对象run()方法。

在项ObjectDemo01类,该类中说明对象是如何调用类成员的。

/*** 例 在项目中创建ObjectDemo01类,该类中说明对象是如何调用类成员的。*/public class ObjectDemo01 {int i = 47;//定义成员变量public void good(){//定义构造方法System.out.println("调用good()方法");for (int i = 0;i < 8;i++) {System.out.print(i + " ");if (i == 7){System.out.println("\n");}}}public ObjectDemo01() {//定义构造方法}public static void main(String[] args) {ObjectDemo01 objectDemo01 = new ObjectDemo01();//创建一个类对象ObjectDemo01 objectDemo02 = new ObjectDemo01();//创建另一个类对象objectDemo02.i = 29;//给类成员变量赋值予29//使用第一个对象类成员变量System.out.println("使用第一个实例对象调用成员变量 i 的结果" + objectDemo01.i++);//使用第一个对象类成员方法objectDemo01.good();//使用第二个对象类成员变量System.out.println("使用第二个实例对象调用成员变量 i 的结果" + objectDemo02.i);//使用第二个对象类成员方法objectDemo02.good();}}

运行结果如下图所示:

在上述代码的主方法中首先实例化一个对象,然后使用“.”操作符调用类的成员变量和成员方法。但是在运行结果中可以看到,虽然使用两个对象调用同一个成员变量,结果却不相同,因为在打印这个成员变量的值之前将该值重新赋值为29,但在赋值时使用的是第二个对象objectDemo02调用成员变量,所以在第一个对象objectDemo01调用成员变量打印该值时仍然是成员变量的初始值,由此可见,两个对象的产生是相互独立的,改变了objectDemo02的 i 值,不会影响到objectDemo01的 i 值,在内存中这两个对象的布局如下图所示:

如果希望成员变量不被其中任何一个对象改变,可以使用static关键字。可以将上述代码改写为以下形式。在项目中创建ObjectDemo02类,该类举例说明对象调用静态成员变量。

/*** 例 在项目中创建ObjectDemo02类,该类举例说明对象调用静态成员变量。*/public class ObjectDemo02 {static int i = 47;//定义静态成员变量public void good(){//定义成员方法System.out.println("调用good()方法");for (int i = 0; i < 8; i++) {System.out.print(i + " ");if (i == 7){System.out.println("\n");}}}public ObjectDemo02() {//定义构造方法}public static void main(String[] args) {//定义main()方法ObjectDemo02 objectDemo01 = new ObjectDemo02();//创建一个对象ObjectDemo02 objectDemo02 = new ObjectDemo02();//创建另一个对象objectDemo02.i = 29;//给类成员变量赋值予29//使用第一个对象调用成员变量System.out.println("使用第一个实例对象调用成员变量 i 的结果" + objectDemo01.i++);//使用第一个对象调用成员方法objectDemo01.good();//使用第二个对象调用成员变量System.out.println("使用第二个实例对象调用成员变量 i 的结果" + objectDemo02.i);//使用第二个对象调用成员方法objectDemo02.good();}}

运行结果如下图所示:

在上述运行结果中可以看到,由于使用objectDemo02.i = 29语句改变了静态成员变量的值,使用对象objectDemo01调用成员变量的值也为29,这正是 i 值被定义为静态成员变量的功效,即使使用两个对象对同一个静态成员变量进行操作,依然可以改变静态成员变量的值,因为在内存中两个对象同时指向同一块内存区域。objectDemo01.i++语句执行完毕后,i 值变为 30。当再次调用call()方法时又被重新赋值为0,做循环打印操作。

三、对象的引用

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

语法如下:

类名 对象引用名称

比如一个Book类的引用可以使用如下代码:

Book book;

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

语法:

Book book = new Book();

·Book:类名。

·book:对象。

·new:创建对象操作符。

注意:引用只是存放一个对象的内存的地址,并非存放一个对象,严格说引用和对象是不同的,但是可以将这种区别忽略,如可以简单的说book是Book类的一个对象,而事实上应该是book是包含Book对象的一个引用。

四、对象的比较

在Java语言中有两种对象的比较方式,分别为“==”运算符与equals()方法,实质上这两种方式有本质区别。

在项目中创建ObjextCompare类,该类说明了“==”运算符与equals()方法的区别

/*** 例 在项目中创建Compare类,该类说明了“==”运算符与equals()方法的区别*/public class ObjectCompare {public static void main(String[] args) {//创建两个String类型对象引用String c1 = new String("abc");String c2 = new String("abc");//将c1对象赋予c3String c3 = c1;//使用 “ == ” 比较c2与c3System.out.println("c2 == c3 的运算结果为 " + (c2 == c3));//使用 “equals()方法” 比较c2与c3System.out.println("c2.equals(c3) 的运算结果为 " + (c2.equals(c3)));}}

运行结果如下图所示:

从上述运行结果中可以看出,“==”运算符和equals()方法比较的内容是不相同的,equals()方法是String类中的方法,它用于比较两个对象引用所指的内容是否相等。而“==”运算符比较的是两个对象引用的地址是否相等,由于c1与c2是两个不同的对象引用,两者在内存中的位置不同,而String c3 = c1;语句将c1的引用赋给c3,所以这c1与c3这两个对象引用是相等的,也就是打印 c1 == c3这样的语句将返回true值。对象c1、c2、c3在内存中的布局如下图所示:

五、对象的销毁

大多数面向对象的编程语言,要求显示地销毁某个对象,这点就没有Java做的好,Java语言提供了垃圾回收机制,对于不再使用的对象会自动销毁,也可以在程序中显示的为某个对象赋值null值,使对象不再被使用。

例如:

whiteCar = null;

垃圾回收器会找到并销毁它,释放该对象所占用的资源。

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

(1)对象引用超过其作用范围,则这个对象将被视为垃圾,如下图所示:

(2)将对象赋值为null。如下图所示:

虽然垃圾回收机制已经很完善,但垃圾回收器只能回收那些由new操作符创建的对象,如果某些对象不是通过new操作符在内存中获取一块内存区域,这种对象可能不被垃圾回收机制所识别,所以在Java中提供了一个finalize()方法,这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法,如果用户在类中定义了finalize()方法,在垃圾回收时首先调用该方法,并且在下一次垃圾回收动作发生时,才能真正回收对象占用的内存。

说明:有一点需要明确的是,垃圾回收或是finalize()方法不保证一定会发生,比如Java虚拟机面临内存损耗待尽的情形,它是不会执行垃圾回收的。

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

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。