·本章学习目标
本章介绍面向对象程序设计的核心内容,是学习这门课程的难点所在。
了解OOP的基本理论,基本概念和基本方法。
掌握类的继承和接口的概念及具体用法。
掌握类的封装、多态性(方法的重载、覆盖)。
掌握静态成员变量和静态成员方法的意义以及引用或调用的方法。
了解包的概念。
·本章学习内容
类和对象的概念
面向对象的特性
类变量和类方法
封装和修饰符的使用
内部类
接口
包层次的理解和使用
3.1 面向对象程序设计基础
3.1.1面向对象概述
面向机器的程序:专门为特定的硬件系统。
面向过程的程序:数据结构和算法,主要以解决问题的过程来编写程序。
面向对象的程序:不仅关心个体的解决过程,而且还关心包含这些过程的复杂系统。
3.1.2面向对象的基本概念
1、类与对象
类(Class):一种复杂的数据类型,它是将数据和与数据相关的操作封装在一起的集合体,是普通数据类型的扩展。它不但包含数据,还包含对数据进行操作的方法(Method),方法反映了数据的行为。
对象(Object):类的实例,它是类的变量,即类在内存中具体的内存分配。
Java编写程序就是编写一个个的类,然后生成一个个的对象。
对象与类是密切相关的,没有脱离对象的类,也没有不依赖类的对象。
2、成员
成员即类中包含的部分。用来描述类(对象)的属性(静态描述对象的特征)和方法(动态描述对象的特征)。
成员变量:类中的数据,用来刻画类的属性。
成员方法:类中一系列的操作(函数),用于描述类的行为。
注意:在Java语言中,一切事物都为对象。
3、类的核心特征
封装:隐藏类的实现细节(具体的代码)。提供类的访问接口。
继承:代码复用,不用改变原代码。用以扩充类的功能。使类具有新的特性。
多态:多种形态。指一个程序中使用相同名字定义了不同的方法。类的实现具有多种形态的特征,具体包括方法的重载和覆盖。
3.1.3面向对象程序设计的优点
提高了程序的可重用性和可维护性;
对数据的封装,提高了数据的独立性;
提高了开发效率,降低修改难度;
对复杂的系统提出了新的解决问题的思路和方案。
3.2 类与对象
3.2.1类的声明和类主体
Java类的定义格式包括类声明和类主体:
<类声明>{ <类主体> }
注:类声明包括该类的名称、访问权限、与其他类的关系等;类主体定义该类的成员。
1、类的声明
类声明的格式如下:
[<修饰符>] class 类名 [extends <父类名>][implements <接口名列表>] { <类主体> }
2、类主体
类主体包含成员变量和成员方法两部分:
<类声明> {
<成员变量的声明>
<成员方法的声明及实现>
}
【例】创建一个名为Person的类,它包含name、age两个成员变量和eat、work两个成员方法。
public class Person {
String name;
int age;
public void eat(){
System.out.println("eat...");
}
public void work(){
System.out.println("work...");
}
}
3.2.2创建对象与构造方法
1、创建与使用对象
定义类之后需要创建类的对象才能使用类的功能。
对象的生命周期是:创建、使用、销毁
类名 对象名; //声明对象变量
对象名=new 类名(); 创建实际的对象
定义好对象后就可以访问对象的方法和变量了,必须遵守先定义创建然后再使用。
创建和使用对象时应注意:
通过“.”运算符实现对成员变量的访问和对成员方法的调用。并不是所有的成员都能够访问,修饰符可以设定访问权限
对象名.方法;
对象名.成员变量;
对象为类的成员时,使用前必须要先创建。
对象作为参数传递的时候为引用调用。
调用方法中没有参数,方法采用空的圆括号;如果有参数,就要在其中提供所有的相符合的参数。
方法可以有返回值或没有,有返回值必须要return语句。
【例】Person类的使用。
public class School {
public static void main(String[] args) {
Person p1 = new Person();
Person p2;
p2 = new Person();
p1.name = "Jack";
System.out.println("p1's name is "+p1.name);
p1.eat();
p2.work();
}
}
2、构造方法
用来构造对象的方法;在创建类的实例的时候对对象的一些成员变量进行初始化。告知系统去如何创建一个符合要求的对象。
修饰符类名([参数[,参数]]){
初始代码块;
}
构造方法名字与所在类相同,无返回值;如果没有构造方法,系统会有一个默认的构造方法;只要定义了一个构造方法,系统就不会再分配默认的构造方法了。
可以有多个构造方法,但是这些构造方法的参数类型或参数列表要不同。此时发生了方法的重载。
【例】使用构造方法为Person_c类的对象赋值。
public class Person_c {
String name;
int age;
Person_c(String n,int a){
name = n;
age = a;
}
public void eat(){
System.out.println("eat...");
}
public void work(){
System.out.println("work...");
}
}
public class School {
public static void main(String[] args) {
Person_c p1 = new Person_c("Jack“,18);
Person p2 = new Person_c(“steven“,25);
System.out.println("p1's name is "+p1.name);
System.out.println("p1's age is "+p2.age);
p1.eat();
p2.work();
}
}
3.3 成员变量和成员方法
3.3.1成员变量的声明
[<修饰符>] [static] [final] [transient] <类型> <变量名>;
static变量为类变量;无static的变量为实例变量;
final变量为常量;
transient变量为临时变量;
类的成员变量独立与方法,在类主体中但不在方法体中,在方法体中的是方法的局部变量。
3.3.2成员方法的定义与实现
成员方法的声明包括方法声明和方法体:
[<修饰符>] <返回值类型> <方法名>([参数列表])[throws <异常类>]{
<方法体>
}
方法中必须要给出方法的返回值,如果没有返回值,返回类型为void,方法后可以跟0个或多个参数;如果没有参数也要跟空的圆括号。
方法体内可以定义变量,称为局部变量;生命周期只在此方法体内。不支持全局变量。
通过类的成员的访问修饰符,来达到对类的成员的控制。
3.3.3类的封装
权限修饰
|
同一类
|
同一包
|
不同包的子类
|
所有类
|
public
|
是
|
是
|
是
|
是
|
protected
|
是
|
是
|
是
|
|
默认
|
是
|
是
|
|
|
private
|
是
|
|
|
|
公有的:可以被所有的类的对象使用。
保护的:被同一类中的其他成员、子类的成员、同一包中的其他类访问。不能被其他包中的非子类访问。
默认的:只能被同一包中的其他类和同一类中的其他成员访问。
私有的:只能被同一类中的成员访问。不能被其他类和其子类访问。
3.3.4实例成员和类成员
1、实例变量和类变量
不使用static修饰的变量为实例变量,创建类的对象会为对象的实例变量分配内存单元。
使用static修饰的变量称为类变量或静态变量,只为该类的第一对象分配内存单元,其后所有创建的对象共享这一变量。
2、实例方法和类方法
不使用static修饰的方法为实例方法,实例方法可以访问类变量,也可以访问实例变量。只能通过对象名调用。
使用static修饰的方法称为类方法或静态方法,类方法只能访问类变量。不能访问实例变量,类方法既可以通过类名调用,也可以通过对象名来调用。
【例】实例成员与类成员的应用。
public class Person_s {
String name;
static int age;
Person_c(String n,int a){
name = n;
age = a;
}
public static void printAge(){
System.out.println(age);
}
public void printName(){
System.out.println(name);
}
}
public class School {
public static void main(String[] args) {
Person_s p1 = new Person_s("Jack“,18);
Person p2 = new Person_s(“steven“,25);
p1.printAge();
p2.printName();
Person_s.printAge();
//Person_s.printName(); //报错
}
}
3.4 类的继承和多态
3.4.1类的继承
1、继承的概念
由已知的类创建新类,新类在原有的类的基础上扩展了功能。通过继承机制,子类能复用父类的代码,同时又允许子类添加自己特有的变量和方法,这样减少了代码的重复,提高了代码的质量和可靠性。
由继承得到的新类称为子类,被继承的类称为超类(父类)。
2、实现类的继承
[<修饰>] class <子类名> extends <父类名>
Ø 继承的原则:
子类继承父类的实例成员和类成员(变量和方法);
子类不能继承父类的构造方法,但可以调用父类的构造方法;
子类可以增加自己的成员。子类中声明了和父类同名同参的方法或变量,则发生了覆盖;
子类重新定义父类的成员方法,则发生了重载;
子类不能删除父类的成员。
子类对父类成员的访问原则:
子类不能访问父类中private的成员;
子类可以访问父类中public和protected的成员;
子类可以访问同一包中父类的默认权限的成员;
子类不能访问不同包中父类具有默认权限的成员。
Ø this和super的使用方法:
在Java中,this用来代表当前正在操作的对象。通过this变量可以引用当前对象的成员变量和方法。
在当前对象内调用:this.成员
在Java中,super用来代表父类。通过super可以引用被子类覆盖的成员:
super.成员
注意:Java不支持多继承,即子类只能有一个父类。
3.4.2类的多态
多态是指一个标识符具有多种语义。
1、方法的重载
同一个类中具有许多同名不同参数列表的方法。
要求:
参数必须不同:个数不同或类型不同或二者都不同;
返回值可以相同也可以不同。
2、方法的覆盖
子类与父类的方法同名同参时,此时子类的方法不能继承父类的该方法,子类的方法覆盖了父类的方法。
要求:
子类不能覆盖父类中声明为final或static的方法;
子类必须覆盖父类中的abstract的方法,或者子类也声明为abstract。
3.4.3最终类和抽象类
1、最终类
不能被继承(不能有子类)的类,使用final来修饰这个类。
如果想保护类中的方法不被子类覆盖,可以用final修饰这个方法为最终方法。
使用final修饰的变量为常量。
2、抽象类
使用abstract修饰的类为抽象类。
抽象类不能实例化。(不能创建抽象类的对象)
抽象类的子类必须实现父类中所有的抽象方法,或者将自己也定义为抽象的。
一个类不能既是抽象类又是最终类。
通过设定方法为抽象方法可以保证该方法在子类中的覆盖(实现),抽象方法只有方法声明而没有方法体。
抽象方法不能是静态方法,也不能是最终方法。而且必须在abstract的类中声明。
3.5 包
3.5.1引用java包
包是一种区别类名的机制,是类的组织形式。
引用已经存在的包的两中形式:
1、前缀引用
java.util.Date today=new java.util.Date();
2、使用import语句
import java.util.*;
3.5.2自定义java包
1、包的定义
package 包名;
package 包名1.包名2;
2、设置包的路径
设置包所在的文件夹,建立包等级,每一个包对应一个文件夹,并且报名与对应的文件夹名称相同。
并将包所在的路径设置到classpath变量中。并修改编译相应的源文件。
3.6 接口和内部类
3.6.1接口
在Java中接口与类有些类似,二者不同之处在于:
接口中定义的变量都是final static类型的,而且接口中定义的方法都是抽象方法。
Java中类的继承不支持多重继承,即一个类只能有一个父类,但是一个类却可以继承(实现)多个接口。因此,声明一个类时不但可以继承一个父类,同时还允许实现多个接口。这可理解为变相的多重继承,弥补了Java的缺陷。
1、接口的声明
与类的声明相似,格式为:
[ <修饰符>] interface <接口名> [ extends <接口名>]{
常量声明;
抽象方法;
}
修饰符只有两种情况:public和省略修饰符;
常量全部隐含为final或static,必须设置初值;
接口中的方法都是抽象方法,抽象方法是只有方法声明而没有方法体的。直接以分号结束。
2、实现接口
实现接口类似继承,在定义类的时候用implements关键字来实现一个接口。
class <类名> implements <接口名>
如果一个类实现一个接口则必须实现接口中的所有方法(完成方法体),且方法必须声明为public。如果确实没有必要实现该方法,也需要将方法完成为空方法。
Java运行多个类实现同一个接口,这些类之间可以是毫无关系的;且一个类可以实现多个接口。
单重继承与多重实现机制
3.6.2内部类
1、概念
内部类就是在类的内部定义的类,可以为类的成员,也可以是方法中定义,还可以在表达式中定义。
包含内部类的类称为外部类。
Ø 内部类的使用:
用在定义他的语句中或语句块中,也可以使用。
可以使用类的成员,也可以使用其所在的方法的局部变量,可以定义为abstract。
若被声明为static则成了顶层类,不能再使用局部变量
如果内部类中有static 成员,则该内部类为static。
Ø 使用内部类的原因以及优缺点:
在事件驱动的程序中经常的使用。
3.6.2内部类的分类
内部类的分类:
非静态成员内部类:作为外部类的成员
静态内部类:作为内部类的静态成员
局部内部类:在方法中定义的内部类
匿名内部类:没有名称,只有类体的局部内部类
3.6.3内部类的使用
在外部类的外部和内部使用成员内部类:
在外部类的外部和内部使用静态内部类:
在方法中定义和使用局部内部类:
匿名内部类的使用:
·小结
面向对象的特征
继承、多态的含义
接口和抽象类的区别
包的使用