《Java04深入面向对象编程》由会员分享,可在线阅读,更多相关《Java04深入面向对象编程(40页珍藏版)》请在金锄头文库上搜索。
1、Java04(Java04(深入面向对象编深入面向对象编程程) )本章内容o类的继承o高级访问控制o包o=运算符与equals()方法oObject类的方法类的继承o继承是面向对象程序设计语言的另一重要特征,理解继承是理解面向对象程序设计的关键,通过继承可以实现代码的复用,使程序的复杂性线性的增长,而不是随规模的增大呈几何级数增长。o在Java中,通过关键字extends继承一个已有的类,被继承的类称为父类(超类,基类),新的类称为子类(派生类)。o在Java中,不允许多继承,即一个类只能有一个父类。车辆车辆机动车机动车非机动车非机动车内燃机车内燃机车电车电车人力车人力车蓄力车蓄力车柴油机车柴
2、油机车汽油机车汽油机车马车马车手推车手推车自行车自行车继承示例类的继承o 继承能够使子类拥有父类的所有的属性和方法,而不需要在子类的类定义时重新定义父类的这些属性和方法,子类即可以保持父类原有的属性和方法,也可以对从父类那里继承而来的属性和方法进行修改,在定义了继承关系后,我们改动父类的一个属性或方法时,子类也会自动改变,但是这些属性和方法必须是非私有,并且没有被子类重新定义的o注:子类拥有父类的所有的属性和方法但不能访问父类中的私有属性与方法一个继承的例子public class Student extends Personprivate int id;public void setId(i
3、nt id)this.id=id;public void study()System.out.println(getName()+ is reading!); public void showInfomation() System.out.println(id:+id+ name:+getName()+ age:+getAge(); public static void main(String args) Student stu=new Student(); stu.setName(zhangsan); stu.setAge(20); stu.study(); stu.showInfomati
4、on(); 构造方法不能被继承o子类不从超类继承构造方法o子类的构造方法一定会调用父类的构造方法,默认调用不带参的构造方法o在子类中用super()来调用父类的构造方法特殊变量supero特殊变量super,提供了对父类的访问。o可以使用super访问父类被子类隐藏的变量或覆盖的方法。o每个子类构造方法的第一条语句,都是隐含地调用super(),如果父类没有这种形式的构造方法,那么在编译的时候就会报错。方法的覆盖(override)o在子类中定义一个与父类同名、返回类型、参数类型均相同一个方法,称为方法的覆盖。o覆盖发生在子类与父类之间。方法覆盖的规则o覆盖方法的返回值类型必须与它所覆盖的方法
5、相同o覆盖方法不能比它所覆盖的方法的访问性差o覆盖方法不能比它所覆盖的方法抛出更多的异常方法的覆盖与重载的区别o方法的覆盖是子类和父类之间的关系,而重载可以是发生在一个类内部多个方法间o方法的覆盖一般是两个方法间的,而重载时可能有多个重载方法o覆盖的方法有相同的方法名和形参表,而重载的方法只能有相同的方法名,不能有相同的形参表o覆盖时区分方法的是根据调用他的对象,而重载是根据形参来决定调用的是哪个方法o用final修饰的方法是不能被子类覆盖的,只能被重载多态的概念o多态是指在一棵继承树中的类可以有多个同名但不同方法体以及不同形参的方法。o有两种情况:o覆盖:在子类中直接定义和父类同样的属性和方
6、法,但重新编写了方法体,即子类与父类方法的形参与返回值都相同,而内部处理不同,这种方法在使用过程中,Java虚拟机会根据调用这个方法的对象来确定哪个方法被调用o重载:同一个类定义中有多个同名的方法,但有不同的形参,而且每个方法有不同的方法体,调用时根据形参的个数和类型来决定调用的是哪个方法对象在继承关系中改变oJava语法规定:o子类实例可以被当作父类的一个对象使用,而父类实例不能被当作子类的一个对象使用o如果一个被父类对象通过赋值指向的地址是子类对象所在的地址,按照前一条准则,这个对象仍然是父类的对象,但它可以通过强制类型转换成子类对象。对象的类型转换o类型转换用来恢复一个对象的全部功能o向
7、上的类型转换(子类转父类)是隐含地实现的o向下的类型转换(父类转子类)必须针对子类,并由编译器检查。也就是说类型转换只能发生在有继承关系的父类与子类之间o可以使用instanceof来测试一个对象的类型类型转换示例Person person=new Person();Student student=new Student();Worker worker=new Worker();person=student;person=worker;worker=(Worker)person;student=(Student)person; /执行出错,抛出ClassCastExceptionworker=
8、(Worker)student; /编译出错,两个对象没有继承关系if(person instanceof Student) student student=(Student)person;if(person instanceof Worker) worker=(Worker)person;多态性的一个呈现o请指出下面代码的执行结果:class Person public void showInfo() System.out.println(i am a person!); class Student extends Personpublic void showInfo() System.ou
9、t.println(i am a student!);class Testpublic static void main(String args) Person p=new Student(); p.showInfo(); 包(package)o为了便于管理大型软件系统中数目众多的类,解决类命名冲突的问题,Java引入了包(package)。包(package)opackage语句必须是文件中的第一条语句。也就是说,在package语句之前,除了空白和注释之外不能有任何语句。o如果不加package语句,则指定为缺省包或无名包。o包对应着文件系统的目录层次结构。o在package语句中,用“.
10、”来指明包(目录)的层次。编译并生成包o在当前目录下生成包 javac d . Test.javao在指定目录下生成包 javac d E:JavaLesson Test.javaimport语句o引入包中的类。 import java.io.File;o引入整个包。 import java.io.*;o在同一包中的类可以互相引用,无需import语句。高级访问控制o类的访问说明符 1、public :能被其它所有的类访问和引用, 可使用 import从另一个包中引入所需要的类,但被 引入的类必须是public 修饰。 2、默认(friendly):只能被同一个包中的类访问和 引用,一个.Ja
11、va文件必须有而且最多有一个public修饰的类,且该类的名称要与.java的文件名一致。高级访问控制o方法的访问说明符 1、 public :如果类也是public 修饰的话,这些属性和方法可以被所有的类访问和使用 2、 private:只能被该类自身访问和调用 3、protected:保护访问控制符,可被同一个包中的 类或不同包中该类的子类以及该类自身访问和引用 4、默认:具有包内访问性,只能被同一个包中的其他类访问和引用方法的访问控制publicprotecteddefaultprivate同类同包子类通用性不同情形下访问说访问说明符明符到此为止-finalofinal在变量之前,则定义
12、一个常量.ofinal在方法之前,该方法不能被覆盖ofinal在类之前,该类不能被继承.常量的定义o使用关键字final定义常量,例如: final double PI=3.1415926;o作为一种约定,在定义常量时,通常采用大写形式。ofinal常量可以在声明的同时赋初值,也可以在构造函数中赋初值。o为了节省内存,我们通常将常量声明为静态的(static)。final方法o为了确保某个函数的行为在继承过程中保持不变,并且不能被覆盖(overridden),可以使用final方法。o为了效率上的考虑,将方法声明为final,让编译器对此方法的调用进行优化。要注意的是:编译器会自行对final
13、方法进行判断,并决定是否进行优化。通常在方法的体积很小,而我们确实不希望它被覆盖时,才将它声明为final。oclass中所有的private和static方法自然就是final。“=”和“equals”的用法o在Java中,boolean、byte、short、int、long、char、float、double这八种是基本数据类型,其余的都是引用类型。o“=”是比较两个变量的值是否相等,“equals”是比较两个对象变量所代表的对象的内容是否相等。o对于基本数据类型的数据,只要他们的值相等,“=”返回trueo对于两个字符串对象,只要他们的内容一致,“equals” 返回true,=返回f
14、alseo对于没有重写equals方法的对象(c1 和c2),“=”和“equals”都返回falseo对于赋值语句后的结果(c1=c2),“=”和“equals”均返回true对象的内存分配图栈内存堆内存str1str2abcabc0088:44000088:44000088:46600088:4660str1标识的对象str2标识的对象 当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并未创建当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并未创建当我们声明一个引用类型变量时,系统只为该变量分配了引用空间,并未创建当我们声明一个引用类型变量时,系统只为该变量分配了引
15、用空间,并未创建一个具体的对象;当用一个具体的对象;当用一个具体的对象;当用一个具体的对象;当用newnew为对象分配空间后,将对象的引用赋值给引用变量。为对象分配空间后,将对象的引用赋值给引用变量。为对象分配空间后,将对象的引用赋值给引用变量。为对象分配空间后,将对象的引用赋值给引用变量。函数的调用o在Java中,传参时,都是以传值的方式进行。o对于基本数据类型,传递的是数据的拷贝;对于引用类型,传递的引用的拷贝。函数的调用xmainchange栈内存y4(3)3(4)43class StringTestpublic static void change(int x,int y)x=x+y;
16、y=x-y;x=x-y;public static void main(String args)int x=3;int y=4;change(x,y); System.out.println(x=+x);System.out.println(y=+y);xy函数的调用ptmainchange栈内存堆内存Point类的对象pt0088:46600088:46600088:4660class StringTestpublic static void change(Point pt)pt.x=pt.x+pt.y;pt.y=pt.x-pt.y;pt.x=pt.x-pt.y;public static
17、void main(String args)Point pt=new Point();pt.x=3;pt.y=4;change(pt);System.out.println(x=+pt.x);System.out.println(y=+pt.y);class Pointint x, y;Object类oObject类是所有类的基类,如果一个类的定义中没有继承任何类,这个类默认继承自Object类oObject类中定义了下列主要方法:protected Object clone()用来生成当前对象的一个拷贝,并返回这个复制对象。public boolean equals(Object obj)用
18、来比较两个对象是否相同。public Class getClass()用来获取当前对象所属类的信息,返回class对象protected void finalize()用来定义回收当前对象时所需完成的清理工作。public String toString()用来返回当前对象本身的有关信息,按字符串对象返回。public int hashCode() 用来返回当前对象的散列码toString方法otoString()方法用于将一个对象的信息变换出字符串后,返回,当我们使用println(obj)来输出一个对象时,默认会调用该对象的toString方法,一个良好的编程习惯是在每一个实体类中,重写t
19、oString()方法,以便于调试,下面是Student类中重写该方法的一个示例:public String toString() return name=+name+ age=+age+; equals方法oequals()用于比较两个对象的内容是否相等,当我们执行两个对象的比较时,需要使用到equals方法,如果被比较的对象没有重写该方法,除非它们指向同一个对象,否则永远返回false,在很多其它的JAVA类的某些方法中(如集合类的contains(obj)方法),默认也会调用该方法,下面是重写学生类的equals方法的一个示例:public boolean equals(Object o
20、bj) if(obj=this) return true; if(!(obj instanceof Student) return false; Student other=(Student)obj; return name.equals(other.getName() & age = other.getName() & sex = other.getSex();getClass方法o该方法返回对象的结果信息,返回值是Class,Class是类结构的封装,是进行类反射的基础,该方法被声明为final的,不能被覆盖,下面的代码演示了如何在程序运行中动态的获取类的完整名字。 Object obj=
21、new Person(); String cName=obj.getClass().getName(); System.out.println(cName);hashCode方法ohashCode方法用于返回一个对象的散列码,该方法在某些需要使用对象散列码值的场合(如该对象作为hashtable的key值时)会被调用,正常情况下,如果两个对象的equals()方法的返回值为true,则这两个对象的散列码也应该相同,下面是Stuent类中对该方法的重写:public int hashCode() return 29*age+name.hashCode()+sex;clone()方法与对象的克隆o
22、clone()方法用于获取对象的一份拷贝,而不是创建一个新的对象,进行clone() 的步骤为: 在派生类中覆盖基类的clone()方法,并声明为public。 在派生类的clone()方法中,调用super.clone()。 在派生类中实现Cloneable接口o为什么我们在派生类中覆盖Object的clone()方法时,一定要调用super.clone()呢?在运行时刻,Object中的clone()识别出你要复制的是哪一个对象,然后为此对象分配空间,并进行对象的复制,将原始对象的内容一一复制到新对象的存储空间中。一个克隆的示例public class Student implements Cloneable public Object clone() try return super.clone(); catch(CloneNotSupportException ex) return null; public Student getMyClone() try return (Student)(super.clone(); catch(CloneNotSupportException ex) return null; Q&A 本章结束本章结束 谢谢大家谢谢大家结束结束