第6章 对象和类
学习目标 理解对象和类以及它们之间的关系 掌握如何定义类并创建类的对象 了解类和对象的UML表示 理解构造函数的作用 理解对象引用,掌握如何向方法传递对象引用 掌握getter、setter方法,掌握this的含义和使用 理解实例变量和方法,静态变量、常量和方法 理解类中变量的作用域 使用对象作为数组元素 掌握package和import语句
面向对象的程序 C语言的面向过程的语言。面向过程的核心: Java语言是面向对象的语言。面对对象的核心: 数据结构 算法 数据加工 封装 继承 多态 对象协作
类和对象 对象(object)表示现实世界中可以明确识别的实体。例如,学生、圆、按钮等。对象具有状态和行为。 类(class)定义了同一类对象共有的属性和方法。 类是对象的模板、蓝图。对象是类的实例。 学习 姓名:张三 行为 (方法) 状态 (变量) 工作 学号:0001 身高:1.73 娱乐
示例 下面是一个圆类: class Circle { double radius = 1.0; Circle() { } Circle(double r) { radius = r; double findArea() { return radius * radius * 3.14159; } } 数据字段 构造函数 方法
类和对象的UML表示 类的UML表示 类名 数据字段 构造函数 方法 对象的UML表示 对象名:类名 数据字段值
构造函数 构造函数(constructor)是一段初始化代码,在new操作符返回新创建对象引用之前,在实例变量被赋予默认初值,并显示初始化之后执行。 语法 constructorDeclaration : modifieropt className (parameterList) { statementsopt } 如果类未定义任何类型的构造函数,编译器会自动提供一个不带参数的构造函数。如果已存在带参数的构造函数,则不会提供不带参数的构造函数。
创建对象 使用new操作符创建对象。 Java虚拟机为新创建的对象分配内存空间,并返回对象的引用。 语法: new ClassName(actualParameterListopt); 例如: new Circle(); //调用无参构造函数 new Circle(5); //调用带有一个参数的构造函数 Java虚拟机为新创建的对象分配内存空间,并返回对象的引用。
引用变量 对象通过引用变量(reference variable)进行访问,引用变量存放的是对象的引用。 声明 引用对象 ClassName objectRefVar; 例如: Circle myCircle; 引用对象 objectRefVar = new ClassName(); myCircle = new Circle();
在一条语句中声明变量和创建对象 合并为一句 ClassName objectReference = new ClassName(); 例如: Circle myCircle = new Circle(); 2.创建对象,返回对象的引用 3.将对象的引用赋值给变量myCircle 1.声明变量,变量类型为Circle,变量名为myCircle
访问对象的实例变量和实例方法 访问对象的实例变量 调用对象的实例方法 objectRefVar.data 例如: myCircle.radius访问对象的radius数据字段 调用对象的实例方法 objectRefVar.method(arguments) myCircle.findArea()调用对象的findArea方法
例6.1 声明类并创建对象 编写程序,定义Circle类,创建Circle对象。 创建一个半径为5的圆。 创建一个半径为1的圆。 显示两个圆的半径和面积。 将第二个圆的半径改为100,显示其半径和面积。 Example:v1/TestCircle.java, v1/Circle.java
基本类型变量和引用类型变量的区别 每个变量表示存储数据的内存单元。 基本类型变量存储的是基本类型的值。 引用类型变量存储的是对象的引用。当变量未引用任何对象时,它是值为null。 基本类型 int i = 1; 引用类型 Circle c = new Circle(); i 1 c 对象的引用
赋值的区别 当进行变量赋值时 基本类型变量赋值时,变量的实际值赋值给另一个变量。 引用类型变量赋值时,对象的引用赋值给另一个变量。 基本类型 i c1 1 对象的引用 赋值前 c2 j 对象的引用 2 不再被引用的对象,将被运行时系统自动回收 i = j; c1 = c2; i c1 2 对象的引用 赋值后 j c2 2 对象的引用
例6.2 使用Java类库中的类 使用javax.swing程序包中的JFrame类创建两个窗体。设置窗体的标题、大小和位置,并显示。 Example:TestFrame.java
类成员访问控制符 类中代码可以访问自身的所有成员。 其它类中的代码访问成员,受访问控制符的限制: private 只能当前类自身可以访问。 package 声明时不带访问修饰符的成员,只有相同包中的代码可以访问。 protected 子类、同一包中的类可以访问。 public 所有其它类都可以访问。 访问控制是在类的层次上进行的,而不是在每个对象上。
Getter和Setter方法 通常为私有(private)域提供Getter和Setter方法。 如果域为datetype propertyName Getter方法用于获取域的值,通常有以下形式的签名: public datatype getPropertyName() Setter方法用于设置域的值,通常有以下形式的签名: public void setPropertyName(datatype value) Example:v2/TestCircle.java, v2/Circle.java
将对象传递给方法 与传递数组一样,传递对象实际是传递对象的引用。 基本数据类型传递的是实际值的拷贝,修改形参,不影响实参。 引用类型变量传递的是对象的引用,通过形参修改对象,将改变实参引用的对象。 实参 : 1 形参 : 1 copy 基本类型 实参 : ref 形参 : ref copy object 引用类型 Example:v2/TestPassObject.java
静态变量 实例变量(instance variable)属于类的具体实例,不能在相同类的实例间共享。 静态变量(static variable)是用static修饰的变量,在一个类的所有实例间共享,也称类变量。 静态变量可以通过类名引用。 1 5 2 radius numberOfObject 表示private + 表示public 下划线 表示static
静态常量 静态常量是用static final修饰的变量。例如,Math类中的常量PI定义为: public static final double PI = 3.14159265358979323846;
静态方法 静态方法(static method)是用static修饰的方法。例如: 静态方法可以通过类名引用。 main JOptionPane.showMessageDialog JOptionPane.showInputDialog Math.random 静态方法可以通过类名引用。 静态方法只能访问类的静态方法和静态变量,不能访问类中的实例变量。
例6.3 使用实例、静态的变量和方法 为v2.Circle添加一个静态变量,保存创建Circle对象的数量。 在main方法中创建circle1和circle2两个对象。 修改实例和静态变量,并查看修改的结果。 Example:v3/TestCircle.java, v3/Circle.java
变量的作用域 成员变量(实例变量和静态变量)的作用域是整个类,与声明的位置无关。 如果一个变量的初始化依赖于另一个变量,则另一个变量必须在前面声明 例如: public class Foo { int i; int j = i + 1; } 如果一个局部变量具有与类中的变量相同的名称,那么局部变量优先,成员变量被隐藏。
this关键字 在实例方法中,实例变量被局部变量或方法参数隐藏,可以通过this.instanceVariable引用实例变量。this表示当前对象。 调用当前类的其它构造函数。 Example:v4/TestCircle.java, v4/Circle.java
对象数组 与基本数据类型一样,可以声明并创建对象数组。 当创建对象数组时,数组元素的缺省初值为null。 Circle[] circleArray = new Circle[10]; for(int i = 0; i < circleArray.length; i++) { circleArray[i] = new Circle(); } 当创建对象数组时,数组元素的缺省初值为null。 circleArray circleArray[0] Circle对象0 数组的引用 circleArray[1] Circle对象1 … … circleArray[9] Circle对象9
例6.7 汇总圆的面积 编写程序,将一个Circle数组的面积相加。 程序创建由10个Circle对象组成的数组 然后以随机数初始化圆的半径 显示数组中所有圆的总面积 Example:v4/TotalArea.java
例6.9 使用Loan类 编写程序,实现一个下面的类并测试。 Example:Loan.java, TestLoanClass.java 年利率,缺省值为2.5 贷款年数,缺省值为1 贷款金额,缺省值为1000 贷款日期 构建缺省的Loan对象 使用给定的值,构建Loan对象 获取年利率 获取贷款年数 获取贷款金额 获取贷款日期 设置年利率 设置贷款年数 设置贷款金额 设置贷款日期 计算月还款额 计算年还款额 Example:Loan.java, TestLoanClass.java
例6.10 整数栈 编写程序,实现整数栈的数据结构。 capacity-1 … 85 10 21 size-1 1 栈顶 42 Example:StackOfIntegers.java, TestStackOfIntegers.java
包 包(package)是相关类和接口的集合,它可以提供访问保护和名称空间管理。 语法 组织功能:将相关的类和接口组织在一起,便于识别和管理 防止命名冲突:不同包中的相同命名,不会产生冲突 访问控制:控制包间的类型的可访问性 语法 package packagename; package语句必须位于源文件的第一条语句,源文件中定义的所有类和接口都属于指定的包。如果没有使用package语句,那么类和接口被放在缺省包(default package)中,缺省包是一个没有名称的包。
包的命名 使用组织的internet域名的反序形式命名包。一个组织内部发生的命名冲突需要由组织内部的约定来处理,通常在组织名称后面包含项目名称。 组织 北京师范大学信息技术与软件工程学院 域名 www.bnuitse.com 包名 com.bnuitse.put com.bnuitse.put.model com.bnuitse.put.view 组织 World Wide Web Consortium 域名 www.w3c.org 包名 org.w3c.dom org.w3c.dom.bootstrap org.w3c.dom.events 组织 The Apache Software Foundation 域名 www.apache.org 包名 org.apache.tools.ant org.apache.tools.ant.helper org.apache.catalina org.apache.catalina.core
引用包成员 用简单名称引用包成员。 Rectangle myRect = new Rectangle(); 用完全限定名称引用包成员 代码与要使用的成员位于相同的包 成员所属的包已经被导入 Rectangle myRect = new Rectangle(); 用完全限定名称引用包成员 使用另一个包中的成员,而且此包未被导入 导入多个包时,出现命名冲突 graphics.Rectangle myRect = new graphics.Rectangle();
导入包成员 将特定成员导入到当前文件中,在文件开始处,类和接口定义之前,package语句之后,加入import语句。 // Painter.java package graphics.app; import graphics.Rectangle; import graphics.Circle; public class Painter { Rectangle myRect = new Rectangle(); Circle myCircle = new Circle(); … }
导入整个包 要导入某个包中的所有的类和接口,应使用具有通配符(*)的import语句。 package graphics.app; // Painter.java package graphics.app; import graphics.*; public class Painter { Rectangle myRect = new Rectangle(); Circle myCircle = new Circle(); … }
静态导入语句 语法 导入类型中的静态成员 import static TypeName.Identifier; Example:StaticImportTest.java, StaticImportOnDemandTest.java
类型查找顺序 当前类型 显式导入的类型 同一包中的其它类型 隐式导入的类型 java.lang Example:graphics/*.java
包的访问 包中顶级类和接口的可访问性 用public修饰的类和接口对包外代码可见 没有用public修饰的类和接口只对包内代码可见