2.2 面向对象
Java是一种面向对象的程序设计语言,了解面向对象的编程思想对于学习Java开发尤其重要。面向对象技术是一种将数据抽象和信息隐藏的技术,它使软件的开发更加简单化,不仅符合人们的思维习惯,而且降低了软件的复杂性,同时提高了软件的生产效率,因此得到了广泛的应用。
2.2.1 面向对象的三大特性
几乎所有面向对象的编程设计语言都离不开封装、继承和多态。
1.封装
面向对象的核心思想就是封装。封装是指将对象的属性和行为进行封装,不需要让外界知道具体实现的细节。封装可以使数据的安全性得到保证,当把过程和数据封装后,只能通过已定义的接口对数据进行访问。
(1)属性:Java中类的属性的访问权限的默认值不是private,通过加private(私有)修饰符来隐藏该属性或方法,从而只能在类的内部进行访问。对于类中的私有属性,要对其给出方法(如:getXxx(),setXxx())来访问私有属性,保证对私有属性操作的安全性。
(2)方法的封装:对于方法的封装,既需要公开也需要隐藏。方法公开的是方法的声明(定义),只需要知道参数和返回值就可以调用该方法;隐藏方法的实现会使已改变的内容对架构的影响最小化。
(3)封装的优点:良好的封装能够减少耦合;类内部的结构可以自由修改;可以对成员变量进行更精确的控制;隐藏信息,实现细节。
2.继承
继承主要指的是类与类之间的关系。通过继承,可以更高效地对原有类的功能进行扩展。继承不仅增强了代码的复用性,提高了开发效率,更为程序的修改补充提供了便利。
Java中的继承要使用extends关键字,并且Java中只允许单继承,即一个类只能有一个父类。这样的继承关系呈树状,体现了Java的简单性。子类只能继承在父类中可以访问的属性和方法,实际上父类中私有的属性和方法也会被继承,只是子类无法访问。
子类并不能全部继承父类的成员变量或成员方法,规则如下:
(1)能够继承父类的public和protected成员变量(方法),但不能继承父类的private成员变量(方法)。
(2)对于父类的包的访问成员变量(方法)的权限,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承。
(3)对于子类可以继承父类的成员变量(方法),如果在子类中出现了同名称的成员变量(方法),则会发生隐藏现象,即子类的成员变量(方法)会屏蔽掉父类的同名成员变量(方法)。如果要在子类中访问父类中同名成员变量(方法),需要使用super关键字来进行引用。
3.多态
(1)多态是同一个行为具有多个不同表现形式或形态的能力。
(2)多态是把子类型对象主观地看作其父类型的对象,因此其父类型就可以是很多种类型。
(3)多态的特性:对象实例确定则不可改变(客观不可改变);只能调用编译时的类型所定义的方法;运行时会根据运行时的类型去调用相应类型中定义的方法。
2.2.2 类和对象
类是一个模板,它描述一类对象的行为和状态。
对象是类的一个实例,有状态和行为。
1.类
1)类的声明
在使用类之前,必须先声明,类的声明格式如下:
[标识符] class 类名称 { //类的成员变量 //类的方法 }
(1)声明类需要使用关键字class,在class之后是类的名称。
(2)标识符可以是public、private、protected或者完全省略。
(3)类名应该是由一个或多个有意义的单词连缀而成,每个单词首字母大写,单词之间不要使用其他分隔符。
2)类的方法
类的方法有四个要素,分别是方法名称、返回值类型、参数和方法体。定义一个方法的语法格式如下:
修饰符 返回值类型 方法名称(参数列表) { //方法体 return 返回值; }
方法包含一个方法头和一个方法体。方法头包括修饰符、返回值类型、方法名称和参数列表。
(1)修饰符:定义了该方法的访问类型,是可选的。
(2)返回值类型:指定了方法返回的数据类型。它可以是任意有效的类型,如果方法没有返回值,则其返回类型必须是void,不能省略。方法体中的返回值类型要与方法头中定义的返回值类型一致。
(3)方法名称:要遵循Java标识符命名规范,通常以英文中的动词开头。
(4)参数列表:由类型、标识符组成的,每个参数之间使用逗号分隔开。方法可以没有参数,但方法名后面的括号不能省略。
(5)方法体:指方法头后{}内的内容,主要用来实现一定的功能。
2.对象
对象是根据类创建的。在Java中,使用关键字new来创建一个新的对象。创建对象的过程如下:
(1)声明:声明一个对象,包括对象名称和对象类型。
(2)实例化:使用关键字new来创建一个对象。
(3)初始化:使用new创建对象时,会调用构造方法初始化对象。
对象(object)是对类的实例化。在Java的世界里,“一切皆为对象”,面向对象的核心就是对象。由类产生对象的格式如下:
类名 对象名 = new 类名( );
访问对象的成员变量或者方法格式如下:
对象名称.属性名 对象名称.方法名()
3.构造方法
在创建类的对象时,对类中的所有成员变量都要初始化。Java允许对象在创建时进行初始化,初始化的实现是通过构造方法来完成的。
在创建类的对象时,使用new关键字和一个与类名相同的方法来完成,该方法在实例化过程中被调用,成为构造方法。构造方法是一种特殊的成员方法,主要特点如下:
(1)构造方法的名称必须与类的名称完全相同。
(2)构造方法不返回任何数据类型,也不需要使用void关键字声明。
(3)构造方法的作用是创建对象并初始化成员变量。
(4)在创建对象时,系统会自动调用类的构造方法。
(5)构造方法一般用public关键字声明。
(6)每个类至少有一个构造方法。如果不定义构造方法,Java将提供一个默认的不带参数且方法体为空的构造方法。
☆注意☆ 类是对某一类事物的描述,是抽象的、概念上的定义,对象是实际存在的该类事物的个体。对象和对象之间可以不同,改变其中一个对象的某些属性,不会影响到其他的对象。
2.2.3 抽象类和抽象方法
在面向对象中,所有的对象都是通过类来实现的,但是反过来,并不是所有的类都是用来描绘对象的,若一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。抽象方法指一些只有方法声明,而没有具体方法体的方法。抽象方法一般存在于抽象类或接口中。
1.抽象类
1)抽象类的使用原则
(1)抽象方法必须为public或者protected,默认为public。
(2)抽象类不能直接实例化,需要依靠子类采用向上转型的方式处理。
(3)抽象类必须有子类,使用extends继承,一个子类只能继承一个抽象类。
(4)子类如果不是抽象类,则必须重写抽象类之中的全部抽象方法。
(5)抽象类不能使用final关键字声明,因为抽象类必须有子类,而final定义的类不能有子类。
2)抽象类在应用的过程中,需要注意以下几点:
(1)抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。只有抽象类的非抽象子类可以创建对象。
(2)抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
(3)抽象类中的抽象方法只是声明,不包含方法体,就是不给出方法的具体实现,也就是方法的具体功能。
(4)构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
(5)抽象类的子类必须给出抽象类中的抽象方法的具体实现,除非该子类也是抽象类。
2.抽象方法
1)抽象方法的声明
声明一个抽象类的语法格式如下:
abstract 返回类型 方法名([参数表]);
☆注意☆ 抽象方法没有定义方法体,方法名后面直接跟一个分号,而不是花括号。
2)抽象方法的实现
继承抽象类的子类必须重写父类的抽象方法,否则,该子类也必须声明为抽象类。最终,必须有子类实现父类的抽象方法,否则,从最初的父类到最终的子类都不能用来实例化对象。
2.2.4 接口
接口在Java编程语言中是一个抽象类型,是抽象方法的集合。接口通常以interface来声明。一个类通过继承接口的方式来继承接口的抽象方法。
1.接口的声明
interface 接口名称 [extends 其他的接口名] { //声明变量 //抽象方法 }
2.接口的实现
当类实现接口时,类要实现接口中所有的方法。否则,类必须声明为抽象类。类使用implements关键字实现接口。在类声明中,implements关键字放在class声明后面。
class 类名称 implements 接口名称[,其他接口]{ … }
3.接口与抽象类的异同
相同点:
(1)都可以被继承。
(2)都不能被直接实例化。
(3)都可以包含抽象方法。
(4)派生类必须实现未实现的方法。
不同点:
(1)接口支持多继承;抽象类不能实现多继承。
(2)一个类只能继承一个抽象类,而一个类却可以实现多个接口。
(3)接口中的成员变量只能是public、static、final类型的;抽象类中的成员变量可以是各种类型的。
(4)接口只能定义抽象方法;抽象类既可以定义抽象方法,也可以定义实现的方法。
(5)接口中不能含有静态代码块以及静态方法(用static修饰的方法);抽象类可以有静态代码块和静态方法。