类和对象
目录
1.1面向对象概述
在程序开发初期人们使用结构化开发语言,但随着软件的规模越来越庞大,结构化语言的弊端也逐渐暴露出来,开发周期被无休止地拖延,产品的质量也不尽如人意,结构化语言已经不再适合当前的软件开发。这时人们开始将另一种开发思想引入程序中,即面向对象的开发思想。面向对象思想是人类最自然的一种思考方式,它将所有预处理的问题抽象为对象,同时了解这些对象具有哪些相应的属性以及行为,以解决这些对象面临的一些实际问题,这样就在程序开发中引入了面向对象设计的概念,面向对象设计实质上就是对现实世界的对象进行建模操作。
1.1.1对象
从 在现实世界中,随处可见的一种事物就是对象,对象是事物存在的实体,如人类、书桌、计算机、高楼大厦等。人类解决问题的方法总是将复杂的事物简单化,于是就会思考这些对象都是有哪些部分组的。通常都会将对象划分为两个部分,及静态部分与动态部分。静态部分,顾名思义,就是不能动的部分,这个部分被称为“属性”,任何对象都具备其自身属性,如一个人,其属性包括高矮、胖瘦、性别、年龄等。然而具有这些属性的人会执行哪些动作也是一个值得探讨的部分,这个人可以哭泣、微笑、说话、行走,这些是这个人具备的行为(动态部分),人类通过探讨对象的属性和观察对象的行为了解对象。
在计算机的世界中,面向对象程序设计的思想要以对象来思考问题,首先要将现实世界的实体抽象为对象,然后考虑这个对象具备的属性和行为。例如,现在面临一只大雁要从北方飞往南方这样一个实际问题,试着以面向对象的思想来解决这一实际问题。步骤如下:
(1)首先可以从这一问题中抽象出对象,这里抽象出的对象为大雁。
(2)然后识别这个对象的属性。对象具备的属性都是静态属性,如大雁有一对翅膀、黑色的羽毛等。
(3)接着识别这个对象的动态行为,即这只大雁可以进行的动作,如飞行、觅食等,这些行为都是这个对象基于其属性而具有的动作。
(4)识别出这个对象的属性和行为后,这个对象就被定义完成了,然后可以根据这只大雁具有的特性制定这只大雁要从北方飞向南方的具体方案以解决问题。
究其本质,所有的大雁都具有以上的属性和行为,可以将这些属性和行为封装起来以描述大雁这类动物。由此可见,类实质上就是封装对象属性和行为的载体,而对象则是类抽象出来的一个实例。
识别对象的属性图
识别对象具有的行为图
描述对象与类之间的关系图
1.1.2类
不能将所谓的一个事物描述成一类事物,如一只鸟不能称为鸟类。如果需要对同一类事物统称,就不得不说明类这个概念。
类就是同一类事物的统称,如果将现实世界中的一个事物抽象成对象,类就是这类对象的统称,如鸟类、家禽类、人类等。类是构造对象时所依赖的规范,如一只鸟具有一对翅膀,它可以用这对翅膀飞行,而基本上所有的鸟都具有翅膀这个特性和飞行的技能,这样具有相同特性和行为的一类事物就称为类,类的思想就是这样产生的。类是封装对象的属性和行为的载体,反过来说具有相同属性和行为的一类实体被称为类。
鸟类结构图
1.1.3 面向对象程序设计的特点
面向对象程序设计具有以下特点: 封装性、继承性、多态性
1.1.3.1封装
封装是面向对象编程的核心思想。将对象的属性和行为封装起来,其载体就是类,类通常对客户隐藏其实现细节,这就是封装的思想。例如,用户使用计算机时,只需要使用手指敲击键盘就可以实现一些功能,无须知道计算机内部是如何工作的,即使可能知道计算机的工作原理,但在使用计算机时也并不完全依赖于计算机工作原理这些细节。
采用封装的思想保证了类内部数据结构的完整性,应用该类的用户不能轻易地直接操作此数据结构,只能执行类允许公开的数据。这样就避免了外部操作对内部数据的影响,提高了程序的可维护性。
封装特性示意图
1.1.3.2继承
类与类之间同样具有关系,如一个百货公司类与销售员类相联系,类之间的这种关系被称为关联。关联主要描述两个类之间的一般二元关系,例如,一个百货公司类与销售员类就是一个关联,学生类与教师类也是一个关联。两个类之间的关系有很多种,继承是关联中的一种。
继承性主要利用特定对象之间的共有属性。例如,平行四边形是四边形,正方形、矩形也是四边形,平行四边形与四边形具有共同特性,就是拥有4条边,可以将平行四边形类看作四边形的延伸,平行四边形复用了四边形的属性和行为,同时添加了平行四边形独有的属性和行为,如平行四边形的对边平行且相等。这里可以将平行四边形类看作是从四边形类中继承的。
图形类层次结构示意图
1.1.3.3多态
介绍了继承,了解了父类和子类,其实将父类对象应用于子类的特征就是多态,多态的实现并不依赖具体类,而是依赖于抽象类和接口。下面以图形类来说明多态。
图形类作为所有图形的父类,具有绘制图形的能力,这个方法可称为“绘制图形”,但如果要执行这个“绘制图形”的命令,没有人知道应该画什么样的图形,并且如果要在图形类中抽象出一个图形对象,没有人能说清这个图形究竟是什么图形,所以使用“抽象”这个词来描述图形类比较恰当。
1.2类
1.2.1成员变量
在Java中对象的属性也称为成员变量,成员变量可以是任意类型,整个类中均是成员变量作用范围。
1.2.2成员方法
在java中有两种成员方法可以获取名称和设置名称分别是 getName()和setName()
定义成员方法的语法格式如下:
权限修饰符 返回值类型 方法名( 参数类型 参数名)throws 异常类型{
…//方法体
return 返回值;}
一个成员方法可以有参数,这个参数可以是对象,也可以是基本数据类型的变量,同时成员方法有返回值和不返回任何值,如果需要就用return关键字,使用这个关键字后,方法的执行就会被终止。 无返回值可以使用viod关键字。
1.2.3权限修饰符
java中权限修饰符主要包括如下图所示;
注意:当声明类时不使用public、protected、defauit、private修饰符设置类的权限,则这个类预设为包存取范围,即只要一个的类可以访问这个类的成员变量或成员方法
packge com.mr;
class AnyClass{
pulic void doString(){
...//方法体
}
}
1.2.4局部变量
局部变量是在方法被执行时创建,在方法执行结束时被销毁。局部变量在使用时必须进行赋值操作或被初始化,否则会出现编译错误。
1.2.5局部变量及其有效范围
可以将局部变量的有效范围称为变量的作用域,局部变量都有效范围从该变量的声明开始到该变量的结束为止,如下图
在相互不嵌套作用域可以同时声明两个名称和类型相同的局部变量,如下图
但是在相互嵌套的区域中不可以这样声明,如果将局部变量id在方法体的for循环中再次定义,编译器将会报错。如下图
1.2.6this关键字
this关键字用于表示本类当前的对象,当前的对象不是某个new出来的实体,而是当前正在编辑的类。this关键字只能在本类中使用。
piblic void setName(String name){ //定义一个setName()方法
this.name=name; //将参数值赋予类中的成员变量
}
其实,this关键字除了可以调用成员变量或成员方法,还可以作为方法的返回值。如下;
public Book getName(){
return this; //返回book类的本类对象
}
1.3类的构造方法
构造方法是一个与类同名的方法,对象的创建就是通过构造方法完成的。每当类实例化一个对象时,类都会自动调用构造方法。
构造方法的特点如下:
(1) 构造方法没有返回类型,也不能定义为void。
(2) 构造方法的名称要与本类的名称相同。
(3) 构造方法的主要作用是完成对象的初始化工作,它能把定义对象的参数传给对象成员。
构造方法的定义语法如下:
public Book() { // 构造方法
.....
}
Public: 构造方法修饰符
Book: 构造方法的名称。
在构造方法中可以为成员变量赋值,这样当实例化一个本类的对象时,相应的成员变量也将被初始化。如果类中没有明确定义构造方法,则编译器会自动创建一个不带参数的默认构造方法。
1.4静态变量和静态方法
在介绍静态变量和静态方法之前,首先需要介绍static关键字,因为由statis修饰的变量和方法被称为静态变量和静态方法。
有时,在处理问题时会需要两个类在同一个内存区域共享一个数据。如下图;
被声明为statis的变量和方法被称为静态成员。静态成员属于类所有,区别于个别对象,可以在本类或其他类使用类名和“.”运算符调用静态成员,语法如下;
类名.静态类成员
如果在执行类时,希望先执行类的初始化动作,可以使用statis定义一个静态区域,这块区域被称为静态代码块。当类文件被执行时,会首先执行static块中的程序,并且只会执行一次。静态代码块的语法如下;
public class example{
static{
.... //可以在这里写初始化的代码
}
}
最后总结以下使用static关键字要注意以下几点:
1.在静态方法中不可以使用this关键字。
2.在静态方法中不可以直接调用非静态方法。
3.局部变量不可以使用static关键字声明。
4.主方法必须用static关键字声明。
5只有内部类可以使用static关键字声明。
1.5类的主方法
主方法是类的入口点,它定义了程序从何处开始。主方法提供程序流向的控制,java编译器·通过主方法来执行程序。语法如下;
public static void main(){
... //方法体
}
在主方法的定义中可以看到以下特性;
1.主方法是静态的,所以如要直接在主方法中调用其他方法,则该方法必须也是静态的。
2.主方法没有返回值。
3.主方法的形参为数组。其中,agrs[0]~agrs[n]分别代表程序的第一个参数到第n个参数,可以使用agrs.length获取参数这个数。
1.6对象
1.6.1对象创建
在之前曾经讲过对象,对象可认为是在一类事物中抽象出某一个特例,可以通过这个特例来处理这类食物出现的问题。在Java语言中,通过new操作符来创建对象。前文在讲解构造方法是介绍过,每实例化一个对象就会自动调用一次构造方法,实质上这个过程就是创建对象的过程,准确地说,可以在java语言中使用new操作符调用构造方法创建对象。语法如下;
Test test=new Test();
Test test=new Test("a");
设置值 | 描述 | 设置值 | 描述 |
test | 类名 | new | 创建对象操作符 |
tet | 创建test类对象 | “a” | 构造方法的参数 |
1.6.2访问对象的属性和行为
用户使用new操作符创建一个对象后,可以使用“对象.类成员”来获取对象的属性和行为。前文已经提到过,对象的属性和行为在类中通过类的成员变量和成员方法的形式来表示的,所以当对象获取类成员时,也相当地获取对象的属性和行为
1.6.3对象的引用
在java中尽管一切都可以看作对象,但真正的操作标识符实质上是一个引用,那么引用在java中是如何体现的呢?语法如下;
类名 对象的引用变量
例如一个people类的引用如下
people tom;
通常一个引用不一定需要有一个对象相关联。引用于对象相关联的语法如下
people tom =new people();
实际上真正的对象是“new people()”这段代码。为了方便开发者保存、调用对象,于是创建来一个people类型、名叫tom的引用变量。实际上,tom只是一段内存地址,用于标记“new.people()"对象在内存中的位置。因为内存地址又长有乱,很难让人记住,所以java语言利用引用变量帮开发者标记内存地址。开发者只要记住引用变量的名字,就能够在内存里找到对象数据。简单来说,tom是new people()的代理人。
既然tom是new people()的代理人,那么new people()对象能做的事,tom也能做。例如下面代码;
new People().getClass();
等价于;
People tom =new People();
tom.getClass();
1.6.4对象的销毁
每个对象都有生命周期,当对象的生命周期结束时,分配给对象的内存地址需要被回收。在其他语言中,需要用户手动废弃的对象。java拥有一套完整的垃圾回收机制,用户不用担心废弃的对象占用内存,垃圾回收器会自动回收无用却占内存的资源。
在学习垃圾回收前,我们应该先了解何种对象会被java虚拟机视为”垃圾“。主要包括以下两种情况;
1.对象引用超过其作用范围,这个对象将被视为垃圾。如下;
2.将对象赋值为null,如下;
虽然java的垃圾回收机制已经很完善了,但是垃圾回收只能回收那些由new操作符创建的对象。某些对象不是通过new操作符在内存中获取存储空间的,这种对象无法被垃圾回收机制所识别。在java中,提供了一个finalize()方法,这个方法是Object类的方法,它被声明为protected,用户可以在自己的类中定义这个方法。如果用户在类中定义了finalize()方法,在垃圾回收是会首先调用该方法,在下一次垃圾回收动作发生时,才真正回收被对象占用的内存。