第3章 面向对象的编程技术
3.1 类 3.1.1 面向对象的概念
3.1 类 3.1.1 面向对象的概念 把问题看成是相互作用的事物的集合,用属性 描述事物,对事物的操作叫做方法,事物称为对 3.1 类 3.1.1 面向对象的概念 把问题看成是相互作用的事物的集合,用属性 描述事物,对事物的操作叫做方法,事物称为对 象,属性称为数据,对象是数据与方法的集合。
3.1 类 3·1·2 类的定义 修饰符 class 类名 [extends 父类名] [implements 接口名] { 3.1 类 3·1·2 类的定义 修饰符 class 类名 [extends 父类名] [implements 接口名] { 修饰符 类型 变量名;//成员变量定义,可选 …… 修饰符 类型 成员方法(参数列表) //开始成员方法的定义 类型 变量名;//局部变量定义,可选 方法体; }
3.1 类 类定义的例子: class Car{ String model; void printModel{ 3.1 类 类定义的例子: class Car{ String model; void printModel{ System.out.println(“The model of this car is”+model); }
3.1 类 类定义的例子: class Person { int age; void introSelf() 3.1 类 类定义的例子: class Person { int age; void introSelf() System.out.println(“I am “+age); }
3.1 类 3.1.3 类的修饰 1.访问控制符 public:公共类,说明这是一个公共类,可以被其它任何类引用和调用 3.1 类 3.1.3 类的修饰 1.访问控制符 public:公共类,说明这是一个公共类,可以被其它任何类引用和调用 不写访问控制符:表示类只能被本包的其它类访问(也称default权限) default权限即包访问权限,该访问控制权规定该类只能被同一个包中的类访问和引用,而不可以被其他包中的类使用,包括import,extends等均不允许。
3.1 类 3.1.3 类的修饰 2.抽象类abstract 表示这个类是个抽象类。抽象类不能直接产生实例化一个对象,它只能被继承。 3.1 类 3.1.3 类的修饰 2.抽象类abstract 表示这个类是个抽象类。抽象类不能直接产生实例化一个对象,它只能被继承。 如果类定义时有abstract关键字,应该放在访问控制符后面,class关键字之前 如:public abstract class{。。。}//类体部分的定义略
3.1 类 3.1.3 类的修饰 3.最终类final 表示这个类是个最终类,最终类将不能被继承,不能再派生出其它子类。 3.1 类 3.1.3 类的修饰 3.最终类final 表示这个类是个最终类,最终类将不能被继承,不能再派生出其它子类。 如果类定义时有final关键字,应该放在访问控制符后面,class关键字之前 思考:类定义时,class关键字之前是否可以同时出现final、abstract两个关键字?如果可以,有无出现先后的位置要求?
3.1.4 属性和方法的声明 1.类的属性 类的属性可以泛指静态属性(成员变量)和动态属性(成员方法) 3.1.4 属性和方法的声明 1.类的属性 类的属性可以泛指静态属性(成员变量)和动态属性(成员方法) 默认情况下,类的属性是指静态属性。即类的成员变量 声明类的成员变量的格式是: [修饰符] 变量类型 变量名[=初值] 修饰符包括访问控制修饰符、静态修饰符static、最终说明符final。
类的属性 访问控制修饰符 private:私有,此成员只能在类的内部使用 默认(default/package):也可以不写访问控制符,成员可被本包的其它类访问 protected:被保护,成员可被本包的所有类访问,也可以被声明它的类和派生的子类访问(家庭成员) public:公共,成员可被所有类访问
类的属性 四种访问修饰符的访问权限如下表所示:
类的属性 访问控制修饰符 访问控制符的使用举例: 见javacode下的access\eg文件夹: Demo1.java~Demo5.java 说明: 关于Protected:protected访问控制符定义中说明的不同包下的子类可以访问,是指子类可以访问父类的成员域,而不是说可以访问父类实例的成员域。
类的属性 访问控制符-总结 访问控制修饰符 public 任何包中的任何类都可以直接访问public变量和方法。 如果一个类中定义了常用的操作,希望能将其作为公共工具供其他的类和程序使用,则应该把该类本身和这些方法都定义成public。如java类库中的那些公共类和公共方法。
类的属性 访问控制符-总结 default 这种访问权限相当于把同一个包中的类作为可信的朋友。
类的属性 访问控制符-总结 protected
类的属性 访问控制符-总结 private: 一般把那些不想让外界访问的数据和方法声明为私有的 有利于数据的安全并保证数据的一致性,也符合程序设计中隐藏内部信息处理细节的原则。
类的属性 static: static修饰符 可以用来修饰类的成员变量,成员方法等
类的属性 类变量/静态变量: static修饰符 以static修饰的变量又称为类变量(静态变量);类中定义的无static修饰的变量称为实例变量。 在类外访问静态变量时,若该静态变量非private,则可以直接用类名访问也可以通过对象访问(两种方式的结果是一样的),实例变量则只能通过实例对象才能访问。 举例见javacode\static文件夹:StaticExample.java,StaticTest.java 编译、运行StaticExample.java文件前可先将第一条语句(package语句注释掉)
类的属性 final修饰符 举例见javacode\final文件夹中的:FinalExample.java 可以通过声明final变量并同时赋初值来定义常量。变量名一般大写:final int NUMBER=100; 被定义成final的成员变量一经赋值就不能改变。 为了节省空间,常常会将static和final连用来达到定义常量的目的。 如果类的final变量在声明时没有赋初值,则在所属类的每个构造方法中都必须对该变量赋值。 可在局部变量(方法中定义的变量)的声明时使用final修饰符 也必须且只能赋值一次,其值在变量存在期间不会改变。 Note:所有final变量必须显式地赋值。 举例见javacode\final文件夹中的:FinalExample.java
3.1.4 属性和方法的声明 2.方法 方法的声明 格式: [修饰符] 返回值类型 方法名(形式参数列表) [throws 异常名列表] { 3.1.4 属性和方法的声明 2.方法 方法的声明 格式: [修饰符] 返回值类型 方法名(形式参数列表) [throws 异常名列表] { //方法体的实现部分; 局部变量声明; 语句序列; }
3.1.4 属性和方法的声明 方法的声明 Note: 方法内部定义的变量称为局部变量。它在方法调用时被创建,在方法调用结束后被销毁。 3.1.4 属性和方法的声明 方法的声明 Note: 方法内部定义的变量称为局部变量。它在方法调用时被创建,在方法调用结束后被销毁。 如果方法指定了非void的返回值类型,则在方法实体中必须有完备的return语句返回需要的返回值。如: boolean checkMinus(int i){ if(i>-1) return false; }
3.1.4 属性和方法的声明 正确的方法定义: boolean checkMinus(int i){ 3.1.4 属性和方法的声明 正确的方法定义: boolean checkMinus(int i){ if(i>-1) return false; return true; }
3.1.4 属性和方法的声明 2.方法 方法的修饰符 访问控制符(含义、作用和属性的访问控制符相同) 静态修饰符static 3.1.4 属性和方法的声明 2.方法 方法的修饰符 访问控制符(含义、作用和属性的访问控制符相同) 静态修饰符static 抽象方法修饰符abstract 最终方法修饰符final等
3.1.4 属性和方法的声明 2.方法 方法的修饰符---静态修饰符static 静态方法:用static修饰符修饰的方法。 (又称类方法) 3.1.4 属性和方法的声明 2.方法 方法的修饰符---静态修饰符static 静态方法:用static修饰符修饰的方法。 (又称类方法) 实例方法:不用static修饰的方法。 二者的区别: 调用方式的不同:实例方法只能在类的实例和子类的实例中调用(也即先要用new运算符创建类的实例,再用 对象名.方法 的方式调用);而由于静态方法属于类,因此只要声明了一个类,不需要实例化对象就可调用其静态方法。
3.1.4 属性和方法的声明 2.方法 方法的修饰符---静态修饰符static 静态方法的编写与使用时应注意的问题: 3.1.4 属性和方法的声明 2.方法 方法的修饰符---静态修饰符static 静态方法的编写与使用时应注意的问题: static方法只能处理static域或调用static方法。 static方法中不能访问实例变量或调用实例方法,也不能使用this或super。 调用static方法时,既可用某一个具体的对象名调用(对象名.方法),也可以使用类名直接调用(类名.方法)(如下页UseStatic.java所示)
//UseStatic.java: Static void main(String args[]) { UseStatic aa=new UseStatic(); UseStatic.j=2; System.out.println(“j:“+ UseStatic.j+”,”+aa.j); aa.j=3; UseStatic.setj(3); aa.i=4; System.out.println(“i=“+ aa.i); aa.seti(4); } //UseStatic.java: class UseStatic { int i; static int j; void seti(int ii) i=ii; } static void setj(int jj) j=jj;
3.1.4 属性和方法的声明 2.方法 方法的修饰符--abstract 被abstract修饰的方法称为抽象方法 3.1.4 属性和方法的声明 2.方法 方法的修饰符--abstract 被abstract修饰的方法称为抽象方法 这种方法只有方法头的声明,没有方法体。 在非抽象的子类中必须有具体的实现。 如果类中存在抽象方法,则该类应定义为抽象类 举例见下页
3.1.4 属性和方法的声明 以下是抽象方法应用的例子,根据所学知识判断该程序是否存在错误,若有则改正它:
3.1.4 属性和方法的声明 2.方法 方法的修饰符—final 被final修饰的方法称为最终方法 3.1.4 属性和方法的声明 2.方法 方法的修饰符—final 被final修饰的方法称为最终方法 final方法不能被子类覆盖,即不能在子类中修改或者重新定义(被定义成final的方法不能在子类中重写(覆盖),若重写,编译时将不能通过) final方法可以被子类继承,用于保护一些重要的方法不被子类修改。 举例见:javacode\final\final修饰方法\FinalTest.java 说明:final类中的方法默认都是final的(但final类中的成员变量并不默认都是final的)。
3.2 对象的实例化 3.2.1 对象的实例化(对象的创建) 对象实例化的格式: 类型 对象名=new 类型([参数列表]); 说明: 3.2 对象的实例化 3.2.1 对象的实例化(对象的创建) 对象实例化的格式: 类型 对象名=new 类型([参数列表]); 说明: “类型”表示对象的类型,必须是复合类型,包括类、字符串等 “对象名”是一个合法的标识符。 “参数列表”要根据类的形式参数确定,与之匹配。(参见例3-8)
3.2 对象的实例化 3.2.1 对象的实例化(对象的创建) 类名 对象名=new 构造方法名(参数列表) Eg: 3.2 对象的实例化 3.2.1 对象的实例化(对象的创建) 类名 对象名=new 构造方法名(参数列表) Eg: class myClass //对象实体的产生 { int data=5;} class Demo { public static void main(String args[]) myClass obj;//定义类类型的变量obj,也称建立一个引用 obj=new myClass(); System.out.println(obj.data); }
3.2 对象的实例化 3.2.2 对象的引用 2.对象方法的引用 1、对象属性的引用 1)person li=new Person(); 3.2 对象的实例化 3.2.2 对象的引用 1、对象属性的引用 类的属性(包括成员变量和成员方法,默认指成员变量)必须要在产生对象即实例化后才能被引用(是指非静态的情况,如果是静态方法或静态变量则可通过类名直接引用:如Arrays.sort(数组变量名);) 引用的方式是:对象名.成员 Eg: 1)person li=new Person(); li.name=“liming”; 2)new Person().name=“liming”; 3)Integer.MAX_VALUE(静态成员可以通过类名直接引用) 2.对象方法的引用 格式:对象名.方法名([参数列表]); 举例见3-4 静态方法的引用:Arrays.sort(数组变量名);
3.2 对象的实例化 3.2.3 方法的参数传递 1.基本数据类型的参数传递 形参类型为基本数据类型(值传递) 3.2 对象的实例化 3.2.3 方法的参数传递 1.基本数据类型的参数传递 形参类型为基本数据类型(值传递) 基本类型的变量作为实参传递,并不能改变这个变量的值 方法中的形式参数相当于局部变量,方法调用结束后自行释放,不会影响到主程序中的同名变量 举例见例3-5
3.2 对象的实例化 3.2.3 方法的参数传递 2.形参类型为引用数据类型(地址传递) 引用数据类型的参数调用可以改变对象的内容 3.2 对象的实例化 3.2.3 方法的参数传递 2.形参类型为引用数据类型(地址传递) 引用数据类型的参数调用可以改变对象的内容 对象的引用变量并不是对象本身,而是对象的句柄(名称),一个对象可以有多个句柄 举例见例3-6
3.2 对象的实例化 3.2.4 对象的消失 Java运行时系统通过垃圾收集器周期性地释放无用对象所占的内存,以完成对象的清除 eg: 3.2 对象的实例化 3.2.4 对象的消失 Java运行时系统通过垃圾收集器周期性地释放无用对象所占的内存,以完成对象的清除 eg: Person li =new Person(); Person wang=new Person(); li=wang;//此时第一条语句创建的Person类的对象没有变量指向它,就成了一个无用对象
3.2.5方法的覆盖与重载 1、方法的覆盖: 子类继承父类时,父类的非private方法会被子类自动继承,且子类中还可添加自己的方法。 如果子类中定义了一个与父类中方法同名的方法,这称为方法的覆盖。 实现方法的覆盖,必须满足下列几点: 完全相同的方法名 完全相同的参数列表 完全相同类型的返回值 访问权限不能缩小,抛出的异常要相同 否则,就不是方法的覆盖,而是子类自己定义的与父类无关的方法。 举例见:p53例3-2
3.2.5方法的覆盖与重载 1、方法的覆盖 “实例方法被覆盖,静态方法被隐藏” (见javacode\Inheritance\TestOverriding文件夹)。 当创建了一个覆盖了父类实例方法的子类时,访问那些被覆盖方法的唯一途径就是在子类中使用super 关键字,任何使用子类的外部类永远不能调用父类的这些被覆盖的实例方法。 父类中的静态方法被子类“覆盖”( 并非真的覆盖,而是子类也具有与父类中同名的静态方法)了,它们仍旧能被访问。只要将子类强制转换为父类的类型就能达到这个目的。
3.2.5方法的覆盖与重载 2、方法重载: 在同一个类中至少有两个方法用同一个名字,但有不同的参数。 不同的参数是指:参数的个数不同,或者是参数类型不同。 说明: 返回类型不能用来区分重载的方法。 重载经常用于构造方法。(参见例3-8) 举例见 :p54 例3-3
3.3 构造方法 3.3.1 构造方法的定义 constructor(构造方法), 是一种特殊的,与类同名的方法。系统在产生对象时会自动执行。通常用于完成对象的初始化工作。 构造方法的特点: 构造方法的方法名与类名相同 构造方法没有返回类型,也不能写void 构造方法的主要作用是完成类对象的初始化工作。 构造方法一般不能由编程人员显式地直接调用,而是用new运算符来调用(参见Person1.java) 在创建一个类的新对象的同时,系统会自动调用该类的构造方法对新对象进行初始化。 参见p57,例3-7
3.3 构造方法 3.3.2 构造方法的重载 (例见3-8) 一个类可以有多个构造方法(重载:在java中,同一个类中可以定义多个同名的不同方法),根据参数的不同(形参的个数,类型,顺序的不同)决定执行哪一个. 如果在定义类对象时没有定义任何构造方法,系统会自动产生一个构造方法,即默认构造方法。默认构造方法不带形式参数,且方法体为空。如:类Car的默认构造方法:public car(){} 若在类定义中添加了带参数的构造方法的定义,则原来默认的空方法将不起作用,要使用空方法必须显式定义。 Note:如果class前面有public修饰符,则默认构造方法的前面也应该有public修饰符。
3.4 this与super 3.4.1 this this在方法体中用来代表当前对象。使用前不需要声明。 使用this来访问当前对象的域或方法(见javacode\this与super\UserInfo.java) 使用this来解决局部变量和域同名的问题(见javacode\this与super\UserInfo.java) 构造方法中使用this([参数列表]),这个构造方法就会调用本类的另一个符合参数条件的构造方法 在一构造方法中,使用this调用本类中其他构造方法时, this([参数列表])语句必须是此构造方法的第一条可执行语句 举例见下页
this变量的使用 在构造方法中使用this调用另一个构造方法 如: class UserInfo{ private String userName; private int userNumber; public UserInfo(String name) { userName=name; } public UserInfo(String name,int number) { this(name);userNumber=number;
3.4 this与super 3.4.2 super的使用 子类的成员方法中,使用super访问父类的域或方法(子类隐藏或覆盖了父类的域或方法时) super访问父类域或变量的格式: super.变量名或super.方法名 举例见: javacode\this与super\TestSuperCity.java 在子类的构造方法中,使用super显式调用父类的构造方法(super([参数列表])) 说明: 使用时, super([参数列表])必须放在子类构造方法的第一句) 如果子类的构造方法中没有super([参数列表])语句,将会隐含调用父类的无参构造方法。 举例见: javacode\this与super\SaloonCar.java
构造方法中使用this,super 总结: this([参数列表]),super([参数列表])语句必须是构造方法的第一条可执行语句。 举例见: MethodOverriding.java,同时注意方法的覆盖问题 TestSuper.java
3.6 字符串的处理 3.6.1与字符串处理相关的类(String&StringBuffer) 3.6 字符串的处理 3.6.1与字符串处理相关的类(String&StringBuffer) String &&StringBuffer :位于java.lang包中,可以直接使用,而不需要使用import语句导入。 String类:用于进行字符串比较、查找等不需要改变字符串内容的相关操作 StringBuffer类:用于实现增加、插入数据到字符串或翻转字符串的内容等改变字符串内容的相关操作 一旦通过StringBuffer类生成了最终的字符串,就可以使用StringBuffer.toString方法将它变为String类
3.6 字符串的处理 3.6.2 字符串的生成与访问 定义字符串变量并初始化的方式 3.6 字符串的处理 3.6.2 字符串的生成与访问 定义字符串变量并初始化的方式 String s=new String(); String s=new String(“abc”);//应避免 Char[] data={‘a’,’b’,’c’}; String s=new String(data); String s=“abc”; Java提供了连接运算符+,可将其它各类型的数据转换为字符串,并连接形成新的字符串 如: String s=“a”+4+”c” 等价于: String s=new StringBuffer().append(“a”).append(4).append(“c”).toString()
3.6 字符串的处理 3.6.3 String类 的常用方法(见书上p63) 1.length() 2.charAt(int n) 3.6 字符串的处理 3.6.3 String类 的常用方法(见书上p63) 1.length() 2.charAt(int n) 3.toLowerCase() 4.toUpperCase() 5.substring(int beginIndex,int endIndex) //返回从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。 6. replace(char oldChar,char newChar) equals(Object anObject) //如果给定对象表示的 String 与此 String 相等(字符序列内容相等),则返回 true;否则返回 false。 。。。
3.6.3 String类 的常用方法 String 类中常用方法的使用: note: 举例见javacode\String&StringBuffer\ StringDemo.java note: String类对象中的内容一旦被初始化就不能被改变。 String类用于比较两个字符串,查找和提取字符串中的子串或字符,实现字符串与其他数据类型之间的相互转换等等操作。
3.6.3 String类 的常用方法 StringDemo.java
StringBuffer类 StringBuffer类用于封装内容可以改变的字符串,可以将其他各种数据类型的数据增加,插入到字符串中,也可以将字符串中的顺序进行颠倒。
StringBuffer类的使用 一旦用StringBuffer生成了最终想要的字符串,就应该用StringBuffer的toString方法将其转化成String类型。随后就可以使用String类的各种方法来操作这个字符串。 举例见 javacode\String&StringBuffer\ StringBufferDemo.java
StringBuffer StringBufferDemo.java运行结果
3.7 JDK的帮助系统 chm格式的JDK文档 chm格式的JDK文档具有更加强大的查询功能,更加适合于初学者使用 如:要查类Integer的方法和有关内容,在左边“索引”标签处,输入要查找的关键字Integer,并回车,系统会显示与Integer有关的类、方法、包 它可以提供类的继承关系、构造方法、常量、方法等详细信息。
作业: p68~69 一、1,2,3,5 二、3,4 三、1,2