JAVA 面向对象基础知识 主要内容: 1.面向对象基本概念 2.Java的类与对象 3.成员变量与封装 成员方法
教学目的和要求: 理解面向对象编程的基本概念 了解类的封装方法 如何创建类和对象 了解成员变量和成员方法的特性 学习使用OOP方式进行程序设计
重点与难点 重点: 类和对象的概念,及实际应用 难点: 类的设计
目 录 1 面向对象的基本概念 2 类 3 对象 4 方法 5 访问控制修饰符 6 静态修饰符、静态字段和方法 7 抽象类与抽象方法 目 录 1 面向对象的基本概念 2 类 3 对象 4 方法 5 访问控制修饰符 6 静态修饰符、静态字段和方法 7 抽象类与抽象方法 8 最终类、最终属性、最终方法与终结器 小结
1 面向对象概念 1、对象 2、对象的封装 3、类和实例 4、消息 5、继承 6、对象之间的关系
1、 对象 对象 (object):面向对象技术的核心。 我们可以把我们所生活的真实世界(Real World)看成是由许多大小不同的对象所组成的。 对象可以是有生命的个体,比如一个人或一只鸟。
对象 对象也可以是无生命的个体,比如一辆汽车或一台计算机。
对象 对象还可以是一件抽象的概念,如天气的变化或者鼠标所产生的事件,或者是一个自然数。 123
对象的属性和行为 环顾周围的世界,任何地方都可以看到对象,例如:人、狗、汽车、计算机、桌子、椅子等等。 不管是有生命的对象还是无生命的对象,它们都有一些共同的特征:属性和行为。
对象的属性和行为 例如,人有姓名、年龄、身高、职业等属性,有工作、吃饭、运动等行为。 而汽车有形状、颜色、品牌等属性,有启动、加速、刹车、转弯等行为。
软件对象 软件对象:现实世界中的对象在计算机中的抽象表示,即仿照现实对象而建立的。 软件对象也有状态和行为,软件对象用变量表示对象的状态、用方法来实现对象的行为。 一个软件对象就是变量和相关方法的集合。 软件对象 = 变量+方法
软件对象的特性 对象名:唯一标识,区别于其它对象的标志,例如car; 变量:对象所处的状态,例如汽车行驶的速度; 方法:通过改变对象的状态,来实现对象的行为,例如通过加速这个方法来改变汽车的速度; 接口:与外界通信的通道。 注意:今后,在不引起歧义的情况下,我们把软件 对象简称为对象。
对象和实体的关系 对象是对现实世界中实体的抽象 Why?实体太复杂啦! How?取其关心的部分! What?对象是抽象的,对象是部分的! 人
2、对象的封装 一个对象的变量(状态)构成这个对象的核心,一般不将其对外公布,而是将对变量进行操作的方法对外公开,这样变量就被隐藏起来。 这种将对象的变量置于方法的保护之下的方式称为封装。 变量 外部访问 方法
2、对象的封装 例如:可以把汽车抽象成一个对象,用变量表示它当前的状态,如速度、油量、所处的位置等,它的行为则可以有加速、刹车、换档等。我们在驾驶汽车时,只需要知道如何操作相应的方法就可以了,不用考虑汽车内部是如何实现诸如提速、刹车等行为。
封装将对象的私有数据隐藏起来,其他对象不能直接访问这些私有数据,必须通过调用该对象的相关方法来间接访问。 公有数据 数据 私有数据 方法 方法 对象A 对象B
对象封装的好处 通过将对象进行封装,能把对别的对象来说并不重要的对象的实现细节隐蔽起来,从而在使用一个对象时,只需知道调用它的方法而无需知道该方法是如何实现的。 (1)模块化:一个对象的源代码的编写和维护独立于其他对象的源代码,而且,对象的使用也很方便; (2)信息隐蔽:每个对象都有一个公共接口使得其他对象可以与其通信,但对象的私有信息和方法则由它自己维护,并且改变这些私有信息和方法不会影响到使用它的其他对象。
3、类 在现实世界里,有许多同“种类”的对象。而这些同“种类”的对象可被归类为一个“类”。 例如,我们可将世界上所有的动物归为动物类,所有的汽车归类为汽车类。 动物类 汽车类
对象与类 类 现实生活中的对象 抽象 软件对象 归类 public class Taxi { int color; int door_number; int speed; public void brake( ) { … } public void speedUp( ) {…} public void slowDown( ) { …} } 现实生活中的对象 抽象 软件对象 public class TaxiApp { public static void main(String args[]) { Taxi t1=new Taxi(); t1.speedUp(); } 归类 类
类的概念 类是对多个具有相似行为的对象的一种抽象,描述了属于该类型的所有对象的性质,即类定义了所有某种类型的对象的共有的变量和方法。 在面向对象的程序设计中,类是程序的基本单元。 Athlete
类与实例 (instance) 汽车类 (class) 实例 (instance) new 你的车 汽车类有些共同的状态(汽缸排气量、排档数、颜色、轮胎数……)和行为(换档、开灯、刹车……),但每一台汽车有个别的状态和方法可以不同于其他汽车。 你的汽车只是这世界中许多汽车中的一个。我们就称你的汽车对象是汽车类中的一个实例(instance)。
对象和类的关系 类是同类对象的集合和抽象 {学生A、学生B……} 学生类 对象是类的一个实例化 学生类学生A
4、消息(message) 单独一个对象一般没有什么用处,在大的应用程序中通常包括许多对象,并通过这些对象之间的交互来完成一个复杂的功能。 例如在多媒体教室教学活动中,包括教师对象、学生对象、计算机对象、投影仪对象、扩音器对象以及桌子等对象,通过这些对象之间的交互才能顺利完成我们的教学活动。
通过各个对象之间的交互,程序就可以实现更高级的功能以及更复杂的行为。 软件对象是通过相互间传递消息来实现交互的。 对象B 对象 A message
当对象A想让对象B执行某项任务时,对象A就向对象B传递消息。有时,接受消息的对象需要了解更多的信息,以明确它该做什么,这时就需要传递一些参数。 例如,要使汽车加速,必须发给它一个消息,告诉它做何种动作(即加速),以及实现这个动作所需的参数(即需要达到的速度等)。 发送消息的实质就是要调用接受消息的对象的方法,所以发送消息可分为三个步骤: (1)确定接受消息的对象; (2)确定调用对象的哪个方法; (3)传递此方法所需要的参数。
一个消息由3个元素所组成: 1.消息目标对象(你的汽车)。 2.执行方法的名字(换档)。 3.执行方法所需用的参数 (parameters)(低、高速档)。 消息的好处 1.一个对象的行为是通过它的方法来表达,所以消息传递支持所有对象之间可能的交互。 2.发送消息的对象与接受消息的对象不需要在相同的程序中,或者相同的机器上。
5、子类和继承 什么是子类? 子类是作为另一个类的扩充或修正所定义的一个类。 bicycle (super class) sub class Mountain bikes Racing bikes Tandem bikes sub class
继承的概念 什么是继承? 继承即子类可以利用父类中定义的方法和变量,就像它们属于子类本身一样。 class Car { int color_number; int door_number; int speed; push_break() { … } add_oil() { … } } class Trash_Car extends Car { double amount; fill_trash() { … } }
类层级(class hierarchy) 类的继承关系不仅仅只是一层关系,它可以有好几层。这种树状关系,我们称作类层级(class hierarchy)。至于层级数可依照实际需要而定 。
类层级(class hierarchy) 不仅如此,子类不受父类的限制,还可增加自己的变量及方法。 子类继承了父类的变量及方法。如此便可重复使用父类中的变量及方法。这就是继承的好处。 不仅如此,子类不受父类的限制,还可增加自己的变量及方法。 例如在出租车中加了一个无线电调用方法,或是在轿车里加了一个卫星导航方法。都是按子类特殊的需要新加的。 因此,我们可以发现越下层的类,其行为越特别。
6、对象之间的关系 包含 继承 关联
包含关系 汽车对象 轮子对象 发动机对象 变速箱对象 座位对象 ……
继承关系 交通工具对象 车对象 汽车对象 公交汽车对象
关联关系 老师对象vs学生对象 汽车对象vs加油站对象 茶杯对象vs茶壶对象
2 类 类是现实世界某些对象的共同特征(属性和操作)的表示,对象是类的实例。 2 类 类是现实世界某些对象的共同特征(属性和操作)的表示,对象是类的实例。 类的属性:类中所包含的各项数据,如变量或其他类的对象,一般称为类的成员变量。 类的服务:类中所包含的成员方法。
2 类 Java语言中,类的来源主要有两种途径: Java类库 用户自定义的类 2 类 Java语言中,类的来源主要有两种途径: Java类库 用户自定义的类 所有的类都是Object类的子类。如果在自定义类时,没有写明父类,则默认的父类为 Object。 从严格意义上讲,Java程序中定义的所有的类都是子类。
[修饰符] class 类名 [extends 父类] [implements 接口名] 2.1 类的定义 [修饰符] class 类名 [extends 父类] [implements 接口名] { 类成员变量声明 类方法声明 } 接口名跟在implements关键字后面,用来说明类中实现了哪个接口定义的功能和方法。 接口是Java用来实现多重继 承的一种特殊机制,我们将在后面详细介绍。 类修饰符用来说明类的特殊性质,分为三种: 访问控制符:public 抽象类说明符:abstract 最终类说明符:final
[修饰符] class 类名 [extends 父类] [implements 接口名] 1.关于类头 [修饰符] class 类名 [extends 父类] [implements 接口名] class关键字的后面,应跟随我们所定义的类的名称。(注意不要把class写成Class)。 父类名跟在extends 关键字后面,用来说明当前类是哪个已经存在类的子类。继承是类与类之间的一种非常重要的关系。 public class Taxi extends Car
2.关于类体 类体主要包括类的具体内容,包括类的属性(成员变量)与方法(成员方法) 。 class <类名> { <成员变量声明> <成员方法声明> } public class Taxi extends Car { public int color_number=2; int door_number; int speed; public void brake (int i, j ) { … } void speedUp( ) {…} void slowDown( ) { …} }
[修饰符] class 类名 [extends 父类] [implements 接口名] 类的属性 public int color_number=2; 类的属性定义语法如下: [修饰符] 变量类型 变量名 [=变量初值]; 变量修饰符用来说明变量的性质,主要有: 访问控制符:public 静态修饰符:static 最终修饰符:final 变量类型和变量名是声明一个变量必不可少的部分;这里的变量的类型是基本数据类型。
类的方法 类的方法有两种作用:一是对类的属性进行各种操作;二是与其他类或对象进行交互,作为一个接口。 方法的声明如下: [修饰符] 返回值类型 方法名 (参数列表) [ throws 异常名1,异常名2,… ] { //方法体: 局部变量声明; 语句序列; } 方法修饰符有四种: 访问控制符:public 抽象修饰符: abstract 静态修饰符:static 最终修饰符:final public void brake (int i, j) { int x, y; x=i; y=j; … }
修饰符的比较 √ × 访问控制符: public, private 抽象修饰符: abstract 最终修饰符: final 静态修饰符: static 类 √ × 变量 方法
2.2 用户自定义类 Java程序设计中,程序员的大部分精力都要放在创建用户自定义类型(user-defined type)上。用户自定义类型也称为自定义类。 每个用户自定义类型(即类)都包含有数据和一组操作数据的方法。类的实例称为对象。 下面,介绍一个简单的 Employee 类。今后,我们在编写职工工资系统时,有可能会用到它。
public Employee (String n, double s, int year, int month, int day) { class Employee { String name; // 成员变量 double salary; Date hireDay; public Employee (String n, double s, int year, int month, int day) { name = n; // 职工姓名 salary = s; // 职工工资 hireDay=new GregorianCalendar (year, month-1, day); //出勤数 } public String getName() // 方法1 return name; …… // 更多的方法 构造方法
2.3 构造方法 定义好一个类以后,我们需要创建该类的实例。在Java中,构造一个类的实例 (即对象),需要做以下三件事情: 2.3 构造方法 定义好一个类以后,我们需要创建该类的实例。在Java中,构造一个类的实例 (即对象),需要做以下三件事情: (1) 为对象分配内存空间; (2) 初始化对象中的成员变量; (3) 调用类的构造方法来创建该对象。 在 Java中,每个类中都至少有一个构造方法。如果没有,则系统会自动提供一个缺省的构造方法。 类的构造方法的作用: (1) 可以保证用户能正确地创建出该类的对象; (2) 可以初始化对象。
构造方法的格式 没有返回值, 也没有void 方法名与类名相同 [修饰符] 方法名 ([形式参数列表]) [throws 异常列表] { 方法体 } 其中,构造方法的修饰符与普通方法的修饰符相同。 一个类可以有多个构造方法,它们都具有相同的方法名,即类名,但是形式参数的个数和类型不同。 在创建对象时,编译器会根据参数的个数和类型来决定调用哪个构造方法。这就是构造方法的多态。
缺省的构造方法 构造方法分为缺省的构造方法(不带参数)和带参数的构造方法。 如果在类中没有定义构造方法,Java会自动为用户提供一个缺省的构造方法。缺省的构造方法确保每个类都至少有一个构造方法。 例如,在类 Employee 中,如果我们没有定义构造方法,则 Java自动提供一个缺省的构造方法,如下: public Employee ( ) //缺省的构造方法 { }
构造方法的例子 【例】下面的例子将建立雇员信息类 EmpInfoA,其中定义了一个构造方法。利用这个构造方法创建一个雇员对象,并初始化该对象,然后输出该对象的若干信息。
构造方法举例 例子:EmpInfoB public class EmpInfoA { String name; // 雇员的姓名 String designation; // 雇员的职务 String department; // 雇员的部门 public EmpInfoA (String n, String des, String dep) { name = n; designation = des; department = dep; } void print ( ) { // 成员方法 System.out.println (name + "是" + department+ "的" + designation); public static void main (String args[ ] ) { // 主方法,程序的入口 EmpInfoA emp = new EmpInfoA ("张三", "经理", "销售部"); emp.print(); // 调用对象emp的方法 print() 例子:EmpInfoB
类成员变量的初始化 对类的成员变量进行初始化,主要有5种途径: 每种数据类型都有默认的初始值; 可以在声明成员变量的同时进行初始值,int i=10; 在类的成员方法中,对成员变量赋值。例如:在main() 方法中; 在类的构造方法中,对成员变量赋值。例如:在前面的构造方法的例子中; 利用初始化块对成员变量进行初始化。初始化块是由一对花括号{ }括起的语句块。
初始化块、构造方法中初始化成员变量 注意:初始化块和构造方法都是在创建对象时被调用。通常,初始化块先执行。 class Point { int x, y; //成员变量 { //在初始化块中初始化 x=10; y=20; System.out.println("在初始化块中进行初始化: x="+ x + ", y=" +y); } Point (int dx, int dy) //在构造方法中初始化 { x=dx; y=dy; System.out.println("在构造方法中进行初始化: x="+ x + ", y=" +y); public static void main (String args[ ] ) { Point p = new Point ( 40 , 40); 注意:初始化块和构造方法都是在创建对象时被调用。通常,初始化块先执行。
3 对象 类是对象的产品模板。 在现实世界里,我们使用的是产品而不是产品的图纸。 同样的道理,Java中运行的应该是由类所创建的对象。 3 对象 类是对象的产品模板。 在现实世界里,我们使用的是产品而不是产品的图纸。 同样的道理,Java中运行的应该是由类所创建的对象。 一个典型的Java程序会创建很多对象,它们通过消息传递进行相互交流,共同完成程序的功能。 一旦任务完成,对象就会被垃圾收集器收回,完成它从创建、使用到清除的生命三步曲。
对象的创建 首先,必须拥有一个合适的类才能创建一个合适的对象,有了合适的对象才能完成合适的工作。 对象创建的语法格式为: 类名 对象名 = new 类名([参数列表]) ; 调用类的 构造方法 对象声明 EmpInfoA emp = new EmpInfoA ("张三", "经理", "销售部");
创建一个对象的三个步骤 类名 对象名 = new 类名([参数列表]) ; 1、对象的声明 格式为:类名 对象名; 例如: People zhangPing; 2、为声明的对象分配内存 new 运算符为声明的对象分配内存,然后调用类的构造方法来初始化对象。用new可以为同一个类创建多个对象,这些对象分别占用不同的内存空间,因此改变其中一个对象的状态不会影响到其他对象的状态。 3、执行构造方法,进行初始化 zhangPing=new People(“20040101”); zhangYong=new People(“20040102”); //创建另一个对象 上面三个步骤,通常可以写成如下简洁的形式: People zhangPing=new People(“20040101”);
创建对象相当于定义一个变量,既可采用上述方法。 People zhangPing=new People(“20040101”); 也可以把上述步骤分开进行,先声明对象, 再实例化对象,最后进行初始化。 People zhangPing; zhangPing = new People(“20040101”);
对象创建的例子 【例】下面的例子将建立雇员信息类 EmpInfoB。利用缺省的构造方法创建一个雇员对象。并且在主方法中初始化该对象,然后打印出该对象的若干信息。
对象创建举例 例子:EmpInfoA public class EmpInfoB { String name; // 雇员的姓名 String designation; // 雇员的职务 String department; // 雇员的部门 void print() { // 成员方法 System.out.println(name + "是" + department+ "的" + designation); } public static void main (String args[]) { // 主方法 EmpInfoB emp = new EmpInfoB(); // 调用缺省构造方法创建对象 emp.name = "张三" ; // 初始化对象 emp的成员变量 emp.designation = "经理" ; emp.department = "销售部" ; emp.print(); // 调用对象emp的方法 print() 例子:EmpInfoA
对象的使用 创建好一个对象之后,就可以使用这个对象。 (1) 访问对象的成员变量:通过运算符 “.” 格式为:对象名.成员变量名 (1) 访问对象的成员变量:通过运算符 “.” 格式为:对象名.成员变量名 例如,在前面例子中:emp.name = "张三" ; 成员变量的访问也可以用new创建对象,然后直接访问,不用先声明对象。例如:new EmpInfoB().name = "张三" 。 (2) 调用对象的方法:也是通过运算符 “.” 格式为:对象名.方法名 ([参数列表]) 例如,在前面例子中:emp.print( ); 同样,我们也可以用new创建对象,然后直接调用它的方法,不用先声明对象。例如: new EmpInfoB().print( )。
4 方法 1 方法概述 Java程序是由一个个类所组成的,类又有两个部分:属性和方法。属性描述类是什么,方法描述类能做什么。 4 方法 1 方法概述 Java程序是由一个个类所组成的,类又有两个部分:属性和方法。属性描述类是什么,方法描述类能做什么。 方法是类的主要组成部分。在一个类中,程序的作用主要体现在方法中。 方法是一个有名字的子程序。通常分为一个主方法和若干个子方法。 主方法调用其他方法,其他方法之间也可以互相调用,同一个方法可以被一个或多个方法调用任意次。
Java程序的基本结构 导入Java类库;// Import… 定义用户类1 { 定义类1的若干变量; 定义类1的方法1; …… 定义用户类1 { 定义类1的若干变量; 定义类1的方法1; …… 定义类1的方法M; } 定义用户类2 { 定义类2的若干变量; 定义类2的方法1; 定义类2的方法N;
方法的类型 方法的类型可分成两种: (1) 标准方法,Java 语言提供了丰富的标准类和标准方法,这些方法提供了程序员所需的许多功能。例如,System.out.println(); (2) 用户自定义的方法,以解决用户专门的需要。 Java 程序的执行是从main方法开始的,调用其他方法后又回到main方法,在main方法中结束整个程序的运行。
2 定义方法 1.声明方法头 2.声明方法体 Java中声明方法的语法如下: [修饰符] 返回值类型 方法名 (参数列表) 2 定义方法 1.声明方法头 2.声明方法体 Java中声明方法的语法如下: [修饰符] 返回值类型 方法名 (参数列表) [ throws 例外名1,例外名2,… ] { //方法体: 局部变量声明; 语句序列; } public void brake (int i, j) { int x, y; x=i; y=j; … }
1、声明方法头 方法头一般由方法名、参数列表、返回类型、方法修饰符和方法抛出的异常五部分组成。 注意事项: (1)方法名可以是任何有效的标识符,命名规则与标识符命名规则相同。 (2)返回类型用来指定方法返回值的类型,方法最多只能返回一个值。 (3)参数列表是方法的输入接口,它列出了一系列形式参数的类型和名称。对于每个行参,调用方法时必须有一个实参与之对应,而且该实参的类型必须与行参的类型一致。
2、声明方法体 方法头定义了方法的性质,方法体则定义了方法的内容。 注意事项: (1)在一个方法中嵌套定义另一个方法将产生语法错误; (2)方法体包含在一对大括号中,即使方法体中没有语句,一对大括号也是必不可少的。 (3)方法头中如果指定了非void的返回值类型,方法体中就必须包含一条return语句,以保证任何情况下都有返回值 。
声明方法体的例子 class Department { int m_DeptNo; //部门编号 String m_DeptName; //部门名称 int m_DeptTotalEmp; //部门雇员数 int getDeptNo( ) //获取当前对象的部门号 { return m_DeptNo; //返回这个对象的部门号 }
3 方法的调用 方法按其被调用的方式可分为两类: 3 方法的调用 方法按其被调用的方式可分为两类: (1)需要程序员书写专门的调用命令来调用的方法,称为程序调用方法,例如 getDeptNo( ); (2)系统自动调用的方法,称为系统方法。例如 main()、action()、paint()、init()等。 这两类方法的定义和使用原则有很大差异。 在某个类中调用该类自身的方法,可以直接使用这个方法的名称;调用其他对象或类的方法,则需要使用该对象或类名作为前缀。
方法的调用 (实例) class Department { int m_DeptNo; //部门编号 String m_DeptName; //部门名称 int m_DeptTotalEmp; //部门雇员数 int getDeptNo( ) //获取当前对象的部门号 { return m_DeptNo; //返回这个对象的部门号 } public static void main(String [ ]args) Department dep=new Department(); dep.m_DeptNo=100; //访问对象dep的成员变量 System.out.println("部门号为:"+ dep.getDeptNo( ) ); //调用对象dep的方法 }}
方法的重载 (Overloading) 同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即形式参数的个数或类型不能完全相同。 例如:几何图形类中有多个方法用来绘制不同的图形,这些方法有相同的名字 draw,但形参不一样, draw (Point a, Point b); draw (Point a, Point b, Point c); draw (Point a, Point b, Point c, Point d); draw (Point a, float radius); 重载 a a d a b a radius b c b c
方法的重载 (Overloading) 几何图形类中有四种不同的绘图方法,我们在调用 draw 方法进行绘图时,是调用其中哪一个方法呢? 其实, 这时Java编译器会根据您提供的实参的类型和个数来决定具体调用其中哪个方法。 例如: draw ( (0, 1), (4, 12) ); draw ( (3, 4), 2.5); 方法重载可以简化程序的编写,您只要记住一个方法名,不需要记那么多复杂的方法名称。通过提供不同的实参就可以调用不同的方法来完成不同的功能。 构造方法也可以重载,其目的是使得用户可以为同一个类创建初始值不同的对象。
class Overloading { void get (int i) { System.out.println("get one int data: i="+ i); } void get (int x, int y) { System.out.println("get two int datas: x="+ x+ " y="+y); void get (double d) { System.out.println("get one double data: d="+ d); void get (String s) { System.out.println("get a string: s="+ s); public static void main( String args[ ]) { Overloading mo=new Overloading ( ); mo.get (1); mo.get (2, 3); mo.get (5); mo.get ("a string");
5 访问控制修饰符 Java 语言新推出 “访问控制修饰符”的概念,允许类创建者声明哪些东西是类使用者可以使用的,哪些是不可使用的。 5 访问控制修饰符 Java 语言新推出 “访问控制修饰符”的概念,允许类创建者声明哪些东西是类使用者可以使用的,哪些是不可使用的。 每个访问控制修饰符都代表一种访问控制权限。 这些访问控制权限按照权限的大小可进行如下排序: public > protected > default(无修饰符)> private
如果一个类没有指定为public,则该类的访问权限就是缺省的。 一、类的访问控制权限(2种) 为类指定访问权限的格式: class 类名; 如果一个类没有指定为public,则该类的访问权限就是缺省的。 [public] 一、类的访问控制权限(2种) public:公共访问权限 default:缺省访问权限
如果一个变量或方法没有指定访问控制修饰符,则该变量或方法的访问权限就是缺省的。 二、变量和方法的访问控制权限(4种) 为类中的变量和方法指定访问权限的格式: [public|private|protected] 数据类型 变量名; [public|private|protected] 返回类型 方法名 (参数列表); 如果一个变量或方法没有指定访问控制修饰符,则该变量或方法的访问权限就是缺省的。 二、变量和方法的访问控制权限(4种) public:公共访问权限 default:缺省访问权限 protected:保护访问权限 private:私有访问权限
5.1 公共访问控制符 public 类的访问控制修饰符只有一个:public。一个类被声明为公共类,表明它可以被所有的其他类所访问。 注意:公共类可以被所有其他类访问不代表公共类中的成员也可以被访问。只有当这些成员也是公共的,才可以访问。 例如:要进入二楼的一个房间,必须首先保证这栋楼的大门是开着的,而且这个房间的门也开着,才可以进入其中。
5.2 缺省访问控制权限 如果一个类前面没有访问控制修饰符,则说明它具有缺省的访问控制权限。 5.2 缺省访问控制权限 如果一个类前面没有访问控制修饰符,则说明它具有缺省的访问控制权限。 缺省的访问控制权限规定类只能被同一个包中的类访问,而不能被其他包中的类访问。 class 类名; default 包1 包2 包3 包n 4 1 …… 8 类
5.3 私有访问控制符 private 用private修饰的变量或方法只能被该类本身所访问,而不能被任何其他的类,包括该类的子类,来访问。 变量1…n 方法1…m 其他类 变量1…n 方法1…m 变量1…n 方法1…m 子类
√ √ √ class Employee { private String name; // 成员变量,私有访问权限 private double salary; public Employee (String n, double s) { // 构造方法 name = n; // 职工姓名 salary = s; // 职工工资 } public String getName() // 方法1 return name; public static void main (String args[ ]) { Employee e = new Employee ("Jack", 2600d); System.out.println("姓名为:" +e.getName()); √ √ √
2. 私有方法 虽然大多数方法是公开的,但是私有方法也经常使用。例如那些与类的访问者无关的方法就可以设置为私有的。 被访问类 访问类 private 方法1(与访问者无关) public 方法2 (与访问者有关) 变量1…n 方法1…m
public class Demo { public int a; // 公共的成员变量 private int b; // 私有的成员变量 public int getA( ) { //公共的成员方法 return a; } private int getB( ) { //私有的成员方法 return b; public Demo (int x, int y) { a = x; //访问公共成员变量,对其初始化 b = y; //访问私有成员变量,对其初始化 public static void main (String args[ ]) { Demo dp = new Demo (1, 2); int w = dp.getA( ); //访问公共的成员方法 System.out.println("变量a的值:" + w); int v = dp.getB( ); //访问私有的成员方法 System.out.println("变量b的值:" + v);
5.4 保护访问控制符 protected 用protected修饰的类成员可以被三种类所访问:该类本身、与它在同一个包中的其他类、在其他包中的该类的子类。 protected 的主要作用:允许位于其他包中的子类来访问父类的成员。 protected 包1 包2 4 1 8 8 假设 包1 中的 类4 不是 包2 中的 类1 的子类 假设 包1 中的 类8 是 包2 中的 类1 的子类
package p1; public class Demopro { public int a; //公共的成员变量 protected void method() //保护的成员方法 { System.out.println ("Demopro中的公共成员变量a的值:"+ a); } package p2; import p1.*; public class test { public static void main (String args[ ]) { Demopro dp = new Demopro( ); dp.method ( ); /* 不能访问 Demopro 中的方法 method,因为 它是受保护的,并且位于不同的包中*/ dp.a = 10; // 可以访问 Demopro 中的公共成员变量 a System.out.println ("Demopro中的公共成员变量a的值:"+ dp.a); }
如果上面的两个类 Demopro 和 test 位于同一个包中,则上面的语句 dp.method ( ) 就不会有错。 如果两个类位于不同的包中且没有继承关系,则对保护类型的变量和方法的访问将受到限制。 因此,上面的 dp.method ( ) 不能正确执行。
√ 归纳上述4种不同的访问控制修饰符: × 同一个类 同一个包 不同包中的子类 不同包中的非子类 private 默认 protected public 权限递增
6 静态修饰符、初始化块和方法 6.1 静态修饰符 static 是静态修饰符,用来修饰类中的变量和方法。 6.1 静态修饰符 static 是静态修饰符,用来修饰类中的变量和方法。 被 static 修饰的变量称为静态变量,静态变量的特点是:它属于类本身,不属于类的任何一个具体对象。 静态变量是一个公共的内存单元。
张三 类 student static int x; x 李四 张三 y 类 student int y; 李四 y 实例化 属于 共享
静态变量 静态变量是类固有的,可以在创建类以后直接访问,而非静态的成员变量只有在生成对象后才存在,才可以访问。 把静态变量称为类变量,非静态变量称为对象变量。相应地,静态方法称为类方法,非静态方法称为对象方法。
class StaticDemo { static int x; //静态变量 int y; //非静态变量 static public int getX() { return x; } //静态方法 public int getY() { return y; } //非静态方法 } public class ShowDemo { public static void main(String[] args) { System.out.println("静态变量x=" + StaticDemo.getX()); System.out.println("非静态变量y="+StaticDemo.getY()); // 非法访问 StaticDemo a= new StaticDemo(); StaticDemo b= new StaticDemo(); a.x=2; a.y=2; b.x=3; b.y=3; System.out.println("静态变量a.x="+a.getX()); System.out.println("非静态变量a.y="+a.getY()); System.out.println("静态变量b.x="+b.getX()); System.out.println("非静态变量b.y="+b.getY());
类的静态成员可以通过 “类名. 成员名” 或者 “对象名. 成员名” 来访问,例如在前面的程序中我们就使用了StaticDemo 类的静态成员可以通过 “类名.成员名” 或者 “对象名.成员名” 来访问,例如在前面的程序中我们就使用了StaticDemo.getX() 和 a.getX() 来访问静态方法 getX() 。 而非静态成员则只能通过 “对象名.成员名” 来访问,例如在前面的程序中我们使用 StaticDemo.getY() 来访问非静态方法 getY() 就会产生错误。 类的静态变量只有一个版本,所有对象访问的都是同一个版本。而非静态变量则有多个版本,创建对象的时候,每个非静态变量都被制作了一个副本,它们之间互不影响。 a b a b x=3 y=2 y=3
6.2 静态初始化块 静态初始化块是由关键字static标识的一对大括号括起的语句组。例如: static { …… } 6.2 静态初始化块 静态初始化块是由关键字static标识的一对大括号括起的语句组。例如: static { …… } 静态初始化块可以用来初始化静态变量。在一个类中只能有一个静态初始化块,并且不能位于任何方法中。
6.3 静态常量 静态变量是很少见的。然而,静态常量却很普遍。例如,Math类中就定义了一个静态常量: public class Math 6.3 静态常量 静态变量是很少见的。然而,静态常量却很普遍。例如,Math类中就定义了一个静态常量: public class Math { …… public static final double PI=3.14159265358979323846; }
6.4 静态方法 静态方法的含义: (1)静态方法属于一个类,不属于具体的对象; 6.4 静态方法 静态方法的含义: (1)静态方法属于一个类,不属于具体的对象; (2)非静态的方法属于某个对象,在这个对象创建时该方法在内存中拥有自己专用的代码段;而静态方法属于整个类,它在内存中的代码段被所有对象共享,不被任何一个对象专有; (3)静态方法不能访问非静态的变量,而只能访问静态变量。
6.5 main方法 main方法是一个静态方法。 每个类都可以有一个main方法。它是程序的入口和出口。
构造方法 构造方法是类的一种特殊方法,它的特殊性主要体现在: (1)构造方法的方法名与类名相同。 (2)构造方法没有返回类型。 (3)构造方法的主要作用是创建类的对象,并对其进行初始化。 (4)构造方法不能由编程人员直接调用,而是在创建对象时被间接调用。 (5)在创建一个类的对象时,系统会自动调用该类的构造方法,并初始化对象。
7 抽象类与抽象方法 abstract 是抽象修饰符,可以用来修饰类或方法。 为什么要引入抽象类和抽象方法呢? 7 抽象类与抽象方法 abstract 是抽象修饰符,可以用来修饰类或方法。 为什么要引入抽象类和抽象方法呢? 一个抽象类可以用来定义一个统一的编程接口,使其子类具有某些共同的特征和行为,但各自的实现细节不同。例如交通工具就可以定义成一个抽象类。 抽象方法可以增加编程的灵活性。
7.1 抽象类 当一个类被声明为abstract时,这个类被称为是抽象类。所谓抽象类就是没有具体实例对象的类。 7.1 抽象类 当一个类被声明为abstract时,这个类被称为是抽象类。所谓抽象类就是没有具体实例对象的类。 人类就是一个典型的抽象类。我们知道,类是对象的集合,对象是类的实例化,而人类这个类却不存在一个属于它的具体对象。 抽象类需要被子类所继承才能生成具体的对象。
7.2 抽象方法 作为方法修饰符,abstract 定义了一种仅有方法头, 而没有方法体的抽象方法。 7.2 抽象方法 作为方法修饰符,abstract 定义了一种仅有方法头, 而没有方法体的抽象方法。 抽象方法属于一种不完整的方法。语法形式为: abstract 返回类型 方法名 (参数列表); 抽象方法只有方法头,而用一个分号来代替方法体(注意:没有花括号)。
注意:所有的抽象方法,都必须存在于抽象类之中。抽象方法不能位于非抽象类中,即如果一个类中有抽象方法,则该类必须为抽象类。 除了抽象方法,抽象类中也可以拥有具体的数据和方法。例如,Person类中可以有一个变量来存储人的名字并且用一个具体的方法来返回它。 Java 中抽象方法是非常重要的概念。在接口中我们将会大量的用到它。
8 最终类、最终变量、最终方法 8.1 最终类 final是最终修饰符,它可以修饰类、变量和方法。 8 最终类、最终变量、最终方法 final是最终修饰符,它可以修饰类、变量和方法。 8.1 最终类 如果一个类被声明为final,意味着它不能再派生出新的子类,不能被其他类继承。因此一个类不能既被声明为abstract,又被声明为final。 将一个类定义为 final 则可以将它的内容、属性和功能固定下来,从而保证可以正确使用这个类所提供的功能。 static只能修饰 变量和方法 abstract只能修饰类和方法
8.2 最终变量 final 修饰的变量即常量。 无论static还是final变量,都只能存储一个数据,而且不得改变。
8.3 最终方法 父类中的方法被声明为final,将不能在子类中被覆盖(重写),即最终方法能被子类继承和使用,但不能被修改或重新定义。 8.3 最终方法 父类中的方法被声明为final,将不能在子类中被覆盖(重写),即最终方法能被子类继承和使用,但不能被修改或重新定义。 之所以要使用final方法,主要出于两方面的考虑: (1)为方法“上锁”,防止任何继承它的子类改变它的本来含义。 (2)提高程序执行的效率。