1、第3章 Java语言面向对象的特征,目标:面向对象的基本概念、类和对象的定义和使用、类的继承和多态、包和接口、几个常用工具类。,第3章 Java语言面向对象的特征,3.1 面向对象的基本概念 3.2 类的定义 3.3 对象 3.4 类的继承和多态 3.5 接口和包 3.6 常用的工具类简介,3.1 面向对象的基本概念,(1) 类和对象 (类型和实例的关系) (2)封装性(属性和行为的封装) (3)继承性(两个类之间的一种关系) (4)多态性(程序中出现的同名现象),3.2 类的定义,(1)类的定义格式(类包括成员变量和成员方法) 修饰符 class 类名 extends 父类名 impleme
2、nts 接口名 类的成员变量定义;类的方法定义; 修饰符:public、默认、abstract、final 【例3-1】:定义了5个成员变量和2个成员方法。,(2)变量 成员变量定义: 修饰符 变量类型 变量名=初值; 成员变量和局部变量的区别:(1)定义位置不同,作用域不同。 成员变量定义在类内部方法之外,局部变量定义在方法内部。 成员变量供所有方法共享,局部变量只在方法内起作用。(2)成员变量可加修饰符,局部变量没有修饰符(final除外)。(3)成员变量可不赋初值(此时它的值为默认值),局部变量必须赋初值。(4)当出现同名的成员变量和局部变量时,局部变量访问优先级高于成员变量。成员变量修
3、饰符: 访问控制符(4种:public、默认、protected、private) 非访问控制符(3种:static、final、volatile),【例3-2】注意三种变量的区别: a:成员变量,用static修饰:静态变量(也叫类变量) b:成员变量,不用static修饰:实例变量(也叫对象变量) c:局部变量,v1.b,v2.b,var.a 供所有对象共享,(3)方法 方法的定义 修饰符 类型 方法名(参数列表)throws 异常类名列表 方法体; 方法的修饰符 访问控制符(4种:public、默认、protected、private) 非访问控制符(5种:abstract、static
4、、final、native、synchronized),方法的参数和返回值 参数可以有,也可以没有,有多个时用逗号分隔,每个参数由类型和参数名构成。 返回值可以有,也可以没有,没有时加void,有时加返回值的类型。 方法的返回值是通过 return 表达式;来实现。表达式的类型与方法定义中的返回值类型要“一致”。,方法调用 定义方法时的参数叫形式参数,简称形参。 调用方法时代入的值叫实际参数,简称实参。 实参个数和类型要和形参保持一致,代入的过程称为参数传递。 形参和实参是两个变量,与是否同名无关。 参数为基本类型时,将实参的值传给形参,形参的改变不会影响实参。参数为复合类型时,将实参的地址值
5、传给形参,形参的改变会影响实参。,【例3-3】,【例3-4】,补充例子(1):下列程序输出结果?public class Test public static void main(String args) int a=1,b=2;swap(a,b);System.out.println(“a=“+a);System.out.println(“b=“+b);static void swap(int a,int b)int t=a;a=b;b=t; ,补充例子(2):下列程序输出结果?public class Test public static void main(String args) St
6、ring a=“abc“;System.out.println(“a=“+a);static void change(String a)a=“def“; ,方法的重载 方法的重载是指在一个类的内部有多个同名的方 法,它们的参数个数或类别不同。 【例3-5】 构造方法 构造方法的特点 构造方法的调用:方法前加new。 构造方法的作用:创建对象并初始化对象的值。 默认构造方法析构方法,(4)实例 【例3-6】 (5)静态变量和静态方法(static) 静态变量和静态方法 静态变量:加static,也叫类变量,属于类。 实例变量:不加static,也叫对象变量,属于对象。静态方法:加static,也
7、叫类方法,属于类。 实例方法:不加static,也叫对象方法,属于对象。,静态变量和静态方法(static),类|静态变量类|静态方法,实例|对象变量1 实例|对象方法1,实例|对象变量2 实例|对象方法2,实例|对象变量2 实例|对象方法2,类的存储区域 (公共资源),对象1、2、3的存储区域,重要规则: 成员之间是并列关系,定义顺序没有先后。 类成员可通过类名或对象名来访问;实例成员只能通过对象名来访问。 类方法只能访问类成员;实例方法既可以访问实例成员也可以访问类成员。 类内部访问实例成员时,对象名用this指代或省略,访问类成员时,类名可省略。,例如: public class A p
8、ublic static void main(String args)f(); static void f() /问main在调用f()时前面省略了什么?,public class A void f()g(); void g() /问f()在调用g()时前面省略了什么?【例3-7】,静态初始化器 完成类的初始化(主要是类变量的初始化),不能操 作实例变量。 定义格式: static 类成员变量初始化; ,(6)抽象类和抽象方法(abstract) 抽象类:被abstract修饰的类。 抽象方法:被abstract修饰的方法。 重要规则 抽象类可有构造函数,但不能直接创建抽象类的对象。 抽象方法
9、没有方法体,而是在方法头的结尾加;abstract 类型 方法名(参数表); 抽象方法只能放在抽象类中,抽象类中可以包括非抽象的方法。,(7)最终类、最终变量和最终方法(final) 最终类:被final修饰的类,不允许被继承(没有子类) 最终变量:被final修饰的变量,不允许改变(符号常量) 最终方法:被final修饰的方法,不允许被覆盖,3.3 对象,(1)对象的定义(生成或创建) 格式:类名 对象名=new 构造方法; 说明: 类和对象的关系,是类型和实例的关系,就好像int类型和int类型变量的关系。 先有类的定义,才有属于该类的对象。,Student类的定义: public cla
10、ss Student String sno, sname,sex;int age,math,chinese,english;public Student(String s,String n,String se,int ag,int m,int ch,int en) sno=s;sname=n;sex=se;age=ag;math=m;age=ag;math=m;chinese=ch;english=en; Student类型对象的创建: Student student1= new Student(“001”,”张三”,”男”,18,78,82,94);Student student2= new
11、 Student(“002”,”李四”,”女”,19,85,64,73);Student student3= new Student(“003”,”王五”,”男”,20,90,80,82);,(2)对象的赋值 对象的初始化 如果对象成员没有赋初值,则它们将获得默认值。 对象成员的表示 对象名.成员名 对象的赋值 对象的赋值实际上是对象各成员变量赋值。 注意:将一个对象赋值给另一个对象时,是将这个 对象的地址值赋给另一个对象的地址值,两者实际 指向同一个对象,相当于一个对象两个名字。 例3-9,(3)对象的使用 对象作为类的成员 例:3-10 对象作为方法的参数 例:3-11 对象作为方法的返回
12、值 例:3-12 对象作为数组元素 例:3-13,3.4 类的继承和多态,类的继承: 继承是两个类的一种关系,一个类可以继承另外一个类的成员,还可以拥有自己的成员,继承者叫子类,被继承者叫父类。 例:Person类 (name,sex,age)Student类 (name,sex,age,speciality)Teacher类 (name,sex,age,department) Java语言仅支持单重继承,即每个子类只允许有一个父类。,类的多态:主要指程序中方法“重名”的现象,多 态有两种表现形式: 重载: 在一个类中定义多个同名的方法。 覆盖: 子类对父类方法的重新实现。,(1)父类和子类
13、创建子类 格式:class 子类名 extends 父类名 如: class Person String name,sex; int age class Student extends Person String speciality; class Teacher extends Person String department; 【例3-14】,继承的传递性 类B继承了类A,类C又继承了类B,这时类C应包含类 A和类B的所有成员及类C自身的成员。【例3-15】,子类对象的初始化 *相关规则: 构造方法是不能被继承的,但是可以在子类的构造方法中调用父类的构造方法。 一个类中没有定义任何构造方法
14、时,系统自动提供一个没有参数的默认构造方法,如果类中已经定义过任何构造方法时,系统将不提供默认构造方法。 一个类中可以根据需要定义多个重载的构造方法。 在定义的构造方法中,可使用this()调用本类其它构造方法,使用super()调用父类构造方法,如果this()和super()都没用,系统会自动加上super()调用父类无参的构造方法。 调用this或super的构造方法必须放在第一条语句,并且this和super最多只可调用其中一条。 【例3-16】,子类和父类对象的转换 *相关规则: 子类对象可以直接赋值给父类对象,此时子类对象被“塑造”成父类对象,子类自己的成员被隐藏了。 父类对象给子
15、类对象赋值时: (1)如果父类对象指向的实际是子类对象,则通过强制转换可以赋值。 (2)如果父类对象指向的不是子类对象,则强制转换也不行。,例: class Aint i; class B extends Aint j; 则 A a=new B();可以,但System.out.print(a.j)错误。 A a=new A(); 则 B b=a; 和 B b=(B)a;都是错误的。 A a=new B(); B b=(B)a;可以。,(2)成员的继承和覆盖 成员变量的继承和隐藏 在子类中,定义一个和父类成员同名的成员变量,称为成员变量的“隐藏”。 规则: 在子类中将继承父类的同名变量“隐藏”
16、了,子类执行继承父类的方法时,使用继承自父类的变量;子类执行自己的方法时,使用自己定义的变量。 如果在子类中引用从父类继承的变量,则可以使用super标识,格式:super. 【例3-18】,成员方法的重载和覆盖 当子类对父类中相同方法头的方法重新定义时,称为方法的覆盖。 覆盖相关规则: 通过子类对象调用方法时,执行的是覆盖后的方法。 如果在子类中调用从父类继承的方法,则可以使用super标识,格式:super.父类方法名(实参) 【例3-19】 【例3-20】,隐藏和覆盖区别:,public class Test public static void main(String args) B
17、b=new B();b.f(); class Aint i=1;public void f()System.out.println(i);class B extends Aint i=2;结果:1,public class Test public static void main(String args) B b=new B();b.f(); class Apublic void f()g();public void g()System.out.println(“aaa“);class B extends Apublic void g()System.out.println(“bbb“); 结
18、果:bbb,成员方法的重载 重载是一个类中包含多个相同名称的方法。 覆盖(Override)和重载(Overload)区别:覆盖是子类对父类方法的重新改写,重载 是类内部的方法间的关系。覆盖要求方法头完全一致,而重载相反, 要求方法的参数个数或类型不同。【例3-21】,3.5 接口和包,(1)接口 接口的基本概念 接口是一种复合数据类型。 接口是由常量和抽象方法组成的特殊类。 接口用于实现类的多重继承,一个类最多只能有一个父类(extends),却可以有多个父接口(implements)。,接口的定义 public interface 接口名extends 父接口名列表 /常量声明 publi
19、cstaticfinal 数据类型 成员变量=常量; /抽象方法说明 publicabstractnative返回类型 方法(参数列表); ,注意: 接口的访问控制符:public或省略 接口的成员方法都是public,abstract的,成员变量都是public,static,final的,即使不写它们。 接口具有继承性,关键字extends,一个接口可以继承多个接口。 一个类也可以“继承”(习惯称为实现)一个接口,关键字implements,一个类可以实现多个接口。 接口不能有构造方法,不能被直接实例化,接口的实现:class 类名 implements 接口列表 注意: 实现用的关键字:
20、implements 如果实现接口的是抽象类则可以不实现接口中的抽象方法,如果不是抽象类则必须实现接口中所有抽象方法。(这点和继承抽象类规则相同。) 实现接口中抽象方法时必须使用完全相同的方法头。特别是在类中实现方法时,public不能省略。 接口和抽象类的区别: 一个类只能继承一个抽象类,但可以实现多个接口。 抽象类可以有构造方法,接口不能有。 抽象类中可以有变量和非抽象的方法,而接口中只能 有常量和抽象方法。 接口比抽象类节省运行开销。【例3-22】 【例3-23】,(2)包 包的基本概念 包是对java中的类进行分类存放的机制,就像通过文 件夹对文件进行分类存放一样。 包的创建 pack
21、age pkg1.pkg2.pkg3; 注: 该语句必须放在文件的首句,可省略,省略时文件中的类放在无名包中。 包对应目录,但目录不一定是包。,包的引用:当一个包中的类用到另外一个包中的类时,需要通过import语句导入。 格式1:import pkg1.pkg2.pkg3.类名 格式2:import pkg1.pkg2.pkg3.* 注: 格式1是加载包中某一个类,格式2是加载指定包中所有类,但不包括子包。 无名包没有指定包名,因此不能被有名的包所引用。,访问控制符的含义,3.6 常用的工具类简介,(1)Java语言的类库 Java提供了很多类供我们调用以提高开发效率,它们按照功能 不同组织
22、在不同的包中: java.lang(语言包) java.util(实用工具包) java.awt(抽象窗口工具包) java.io(输入输出流包) (网络包) java.sql(数据库访问包) javax.swing(用于图形用户界面(GUI)设计) 如果要使用上述包中的类需要通过import语句导入。(java.lang除外,该包自动加载),说明:Java系统类有几千个,全部记住它们的用法是不可能的,也是没必要的,用到相关类时可查看类库说明手册(JAVA5.0API_CN.CHM),本节只介绍java.lang(基础类库)中常用类的用法,其他包在后面章节中陆续介绍。,(2)Java语言基础类
23、库(java.lang.*) Object: Java程序中所有类的直接或间接父类,处在类层次最高点。,Object类定义了所有对象必须具有的状态和行为,较主要的方法如下: public final Class getClass() 获取当前对象所属的类信息,返回Class对象 public String toString() 返回当前对象本身的有关信息,按字符串对象返回 public boolean equals(Object obj) 比较两个对象是否是同一对象,是则返回true protected void finalize() 定义回收当前对象时所需完成的资源释放工作,相等和同一的概念
24、 两个对象具有相同的类型,及相同的属性值,则称二者相等(equal) 如果两个引用变量指向的是同一个对象,则称这两个变量(对象)同一(identical) 两个对象同一,则肯定相等 两个对象相等,不一定同一 比较运算符“=” 判断的是这两个对象是否同一例:3-25,Math类:提供了一些常用的数学常量和数学运算方法,这些方法都是static的,使用时直接通过类名来调用。 abs,exp,floor,log,max,min,pow, random,rint,sqrt,sin,cos,tan等。例【3-26】,System类: 三个属性:in,out,err 三个方法: currentTimeMi
25、llis():返回以毫秒为单位的当前时间。 exit(int status):结束当前运行的程序,并将状态信息status返回到操作系统。 gc():强制调用Java虚拟机的垃圾回收功能。思考:如何计算一段代码的运行时间?,String类: 构造方法,length(),indexOf(),compareTo(), equals(),equalsIgnoreCase(),charAt(), substring()等。注意:判断两个字符串s1和s2是否相等,要用 s1.equals(s2),千万不要用s1=s2例:【3-27】,【3-28】,StringBuffer: 构造方法,length,ca
26、pacity,append,insert等。【3-29】,补充:基本数据类型包装类,Java的每一个基本数据类型都有一个数据包装类与之对应。,生成数据类型包装类对象的方法 从基本数据类型的变量或常量生成包装类对象 double x = 1.2; Double a = new Double(x); Double b = new Double(-5.25); 从字符串生成包裹类对象 Double c = new Double(“-2.34“); Integer i = new Integer(“1234“); 已知字符串,可使用valueOf方法将其转换成包装类对象: Integer.valueO
27、f(“125“); Double.valueOf(“5.15“);,得到基本数据类型数据的方法 每一个包装类都提供相应的方法将包装类对象转换回基本数据类型的数据 anIntegerObject.intValue() / 返回 int类 aCharacterObject.charValue() / 返回 char类型的数据 Integer、Float、Double、Long、Byte 及Short 类提供了特殊的方法能够将字符串类型的对象直接转换成对应的int、float、double、long、byte或short类型的数据 Integer.parseInt(“234”) / 返回int类型的数据 Float.parseFloat(“234.78“) / 返回float类型的数据,思考: 如何将数值12转化为字符串“12”?12+”; 如何将字符串“12”转换为整数12?Integer.parseInt(“12”)类似的:Double.parseDoube(“12.1”) 如何取出字符串s的每一个字符?s.charAt(i) 如何把9转换为数值99-0,