zoukankan      html  css  js  c++  java
  • Java知识点滴(四)

    第四章 继承和多态性

    56、(P176) 应用面向对象技术的最大优点是程序代码的可重用性。设计一个类应尽可能增加它的可重用性,其原则是设计一个类应实现定义明确的单任务,而不是用多个任务去加重该类的负担。

    57、(P179 - P187) Java的继承机制:注意以下几点,a) Java与C++不同,只有公有继承方式而没有私有继承方式; b) Java只支持单继承,而不支持多继承,对于现实世界中大量存在的多继承关系是采用接口(interface)类型实现的;c) Java除了提供一个this引用外,还提供了一个Super引用变量,它是用来替代直接超类(即父类),但不能代替间接超类;d) 超类的对象引用可以用来指向它的任何子类(不管是直接子类还是间接子类)的对象,但反之不成立,即子类的对象引用是不能指向它的超类对象的。

    58、(P179) Java的公有继承特性一: 子类将继承超类的所有字段(包括成员变量和常量)和方法,不管它是公有的、保护的还是私有的。即超类的所有字段和方法都自动成为子类的字段和方法,因此,子类体内只需写出新增的字段和方法。同时,在子类体内它们的访问权限不变,即原来公有的在子类仍是公有的,原来是保护的在子类仍是保护的,原来是私有的在子类仍是私有的。

    59、(P179 - P180) Java的公有继承特性二: 父类和子类的对象可以直接访问(即用.号操作符)对象自己的公有字段和公有方法,但不能直接访问自己的私有字段和私有方法、保护字段和保护方法。那些私有和保护字段只有通过对象调用公有方法才能访问到。但是, 父类和子类中的任何方法都可以直接访问该类的各字段和方法,不管这些字段和方法是公有的、私有的还是保护的。

    60、(P180) Java的公有继承特性三: 不管是直接子类的对象还是间接子类的对象都可以访问公有超类或同一个程序包内友元超类中的公有字段和公有方法,而不能访问它们私有的和保护的字段和方法。

    61、(P181) Java的公有继承特性四: 在子类的任何方法体内,不仅可以访问超类的公有字段和公有方法,而且也可以访问超类的保护字段和保护方法,且这种性质还具有传递性,只要是继承链上的超类,都是如此。但是却不能访问超类的私有字段和私有方法。私有的字段和方法只有通过调用超类自身的公有方法才能间接访问到。    子类继承了超类的所有字段和方法,不管是公有、保护、私有的,只不过私有的无法直接访问,必须通过超类的公有方法才能间接访问到。

    62、(P182) Java的继承特性:所有类都是从系统提供的java.lang.Object类中继承来的。Object类是所有类的顶级类。若有的类没有指明它的直接超类,则都隐含着直接超类为Object类。

    63、(P185) 超类和子类:可以把一个子类的对象引用赋给超类的对象引用,或者直接令超类的对象引用指向一个新创建的子类对象。超类和子类对象引用的赋值规则是单方向的。这种赋值常常发生在调用一个方法时,该方法的一个形参是超类的对象引用,而实参可以是它的任何子类(直接子类或间接子类都可以)的对象。   相反,把父类的对象引用赋给子类的对象引用必须用强制类型转换。

    64、(P187) 构造方法的继承之一:子类将无条件地继承父类的所有方法,但不继承父类的构造方法。  当子类一个构造方法也没有,或者在无参数构造方法体内没有显式调用父类的无参构造方法时,系统将自动提供一个父类的无参构造方法来初始化从父类继承来的成员变量。  因为在条用子类的无参数构造方法时会隐含调用超类的无参构造方法,因此,在子类的无参构造函数中不必写super();语句。

    65、(P187) 构造方法的继承之二:在编写子类的带参数构造方法时,对于从超类继承而来的那些成员变量,在其方法体内可用super(参数表);语句调用超类的带参数构造函数来初始化它们,但超类应具有相匹配的带参数构造方法,且该语句必须是子类构造方法的第一条语句。

    66、(P187) 构造方法的继承之三:超类和子类构造方法的调用顺序是,先执行父类的构造方法初始化从父类继承而来的成员变量,再调用自己的构造方法初始化本类新增的成员变量。

    67、(P189 - P190) Java的多态性(Polymorphism): 多态性指程序代码可以根据运行情况不同执行不同的操作。当超类的方法在子类中重新定义时,其结果是使对象呈现多态性。因此,不是整个类都具有多态性,而是只有类的方法函数具有多态性。Java的多态性主要表现在方法的重载(overload)和方法的覆盖(override)。

    68、(P190) 实例方法的重载与覆盖:实例方法的重载完全遵循第3章所说的规则,在一个类体内或者是该类的子类体内所定义的方法名可以重复使用,即再定义一个名字相同但参数表不同的方法,构成多个重载方法(overload)。      当一个类扩展成子类时,在子类体内对该方法重新编写一个具有新功能的方法体,而方法头与超类的该方法完全相同(即,方法的参数表和返回类型都不变而方法体重新编写),这就是方法覆盖(override)。

    69、(P192) 实例方法的覆盖:若子类有一个名字、返回类型和参数表与超类完全相同的方法,则将产生方法覆盖,对于实例方法这种覆盖实际上是置换,就是被代替了。此时,子类的对象就不能再访问被置换掉的方法,只有用super引用变量才能访问到它。      超类中的每个方法在任一个子类中都只能被至多一个方法所覆盖,且它的访问权限不应该低于被覆盖的方法。例如,若超类是公有方法则子类中覆盖它的必须是公有的。

    70、(P193) 类方法的隐藏:子类中的类方法将隐藏从超类继承下来的名字、返回类型和参数表与其完全相同的类方法。子类的对象若要调用被隐藏的类方法,则可以用一个超类的对象引用指向该子类的对象,再用该对象引用去调用被隐藏的类方法。

    71、(P194) 静态联编和动态联编:把一个方法函数与一个方法体链接起来的操作称为“联编(binding)”。在程序运行之前编译时就进行的联编称为静态联编(static binding)或先期联编(early binding), 在运行期间根据对象的类型才能决定链接哪一个方法体的联编成为动态联编(dynamic binding)或后期联编(late binding)。    c语言的所有函数都是静态联编;c++语言既有静态联编,也有动态联编;Java语言全部是动态联编,即所有的方法调用都自动地进行动态联编,这便于编写各种复杂的、灵活多变的、如“单接口多实现版本”的程序框架。

    72、(P196) 动态联编在“单接口多实现版本”的程序框架中的应用:在一个类体内设计一个方法,应先使用某个超类的对象引用作为形参构成一个单接口,再利用“一个超类的对象可以用来处理从它继承下来的所有子类的任一对象”这一重要规则,在各层的子类体内编写各种不同实现版本,即不同方法体但方法函数名字、返回类型和参数表都完全相同的方法以实现方法覆盖,则构成了一个“单界面多实现版本”的程序框架。例如, A类体内定义了MA方法,并用超类P的一个对象p作为MA方法的形参,这就是一个单界面。超类P扩展有两个直接子类S和T, 对于超类P中的实例方法area(), 子类S和T中都予以覆盖。若调用MA()方法时,实参是S类的对象,则执行p.area()时,将调用S类的area()方法计算;若实参是T类的对象,则执行p.area()时,将调用T类的area()方法计算。

    73、(P197) 类的修饰符:类的修饰符分为访问控制修饰符和非访问控制修饰符两大类。除了用访问控制修饰符指定访问的范围外,还可以在访问控制修饰符之后使用两个非访问控制修饰符 abstract 和 final,用 abstract 修饰的类称为抽象类,而用 final 修饰的类称为最终类。

    74、(P198 - P199) 抽象类:用abstract修饰的方法称为抽象方法,它只有方法头并在其后用一个分号来代替方法体,即抽象方法不提供具体实现它功能的方法体。当定义一个类时只要有如下的某一个条件成立,就必须用修饰符 abstract 把该类定义为抽象类:a) 该类包含一个或多个抽象方法;b) 该类从它的抽象父类继承了一个或多个抽象方法,但本类又没有提供具体的实现部分;c) 该类用关键字 implements 声明是一个接口的具体实现,但又没有给该接口的任何方法提供具体的实现部分。     总之,只有抽象类才能包含抽象方法。

    75、(P199) 抽象类的性质:a) 抽象类是一种不完整的类,它不能实例化为具体对象。b) 抽象类可以包含非抽象方法,它还可以包含成员变量和初始化它们的构造方法,当它的非抽象子类实例化时,可调用抽象类的构造方法初始化这些成员变量。c) static 和 private不能与abstract组合起来使用。 d) 抽象类可以含有它的构造方法,但不能用abstract修饰构造方法。 e) 定义抽象方法时必须没有方法体,即抽象方法不能在它的抽象类中实现,而必须在它的非抽象子类中实现。

    76、(P200) 最终类:用final修饰的成员变量就是一个常量字段,用final修饰的方法称为最终方法,用final修饰的类成为最终类。

    77、(P200) 最终类的性质:a) 将一个类声明为最终类则它不能再有子类。这可给安全方面带来极大的好处。 b) final和 abstract不能组合起来修饰同一个类。c) 在一个类的类体中,用final修饰的方法称为最终方法。其子类不能再定义一个原型相同的方法覆盖它。c) 最终类的所有方法都被默认为是最终方法,另外,私有方法也被默认为是最终方法。

    78、(P200) 接口(interface):在Java中,接口类型是抽象类概念的进一步升华,也是实现多重继承的一种结构。接口本身不提供实现功能的方法体,而由“继承”这个接口功能的各个类来具体实现。     接口与抽象类明显不同之处是,它的方法可以在不是继承链的类中实现,从而为相互没有关系的类能实现同样功能的一组方法提供一种有效手段。

    77、(P201 - P206) 接口的性质:a) 用于接口的访问修饰符只有public 一个,即只有两种访问控制权的接口,一种是用public修饰的接口,另一种是没有访问控制符的接口,它隐含地把访问权限限制在一个程序包内。  b) 接口类型象class类型一样可以继承,通过继承可以扩展接口。接口类型不仅可以单继承还可以多继承。  c) Java的类层次结构中有一个顶级类 Object, 但接口层次中不存在一个这样的顶级接口。 d) 接口体内只能声明常量字段和抽象方法,并且字段被隐式地指定是 public 型的,又是 static 型的和 final 型的。接口内的方法被隐式地指定为public 型和 abstract 型。

    78、(P201) 接口类型的实现:a) 对于接口体内所声明的一组抽象方法,还必须用一个类具体实现这些抽象方法。在Java中都把对接口的“继承”称为“实现”,把对接口中抽象方法的覆盖称为“实现抽象方法”。 b) 一个类可以实现多个接口功能。 c) 当实现接口功能的这个类是抽象类时,它可以不实现接口的所有抽象方法。 d) 在这个类中实现某接口的抽象方法时,必须使用与该抽象方法完全一样的名字、返回类型和参数表,才产生方法覆盖,从而实现该抽象方法。若参数表有所不同,将只是重载了一个新的方法,而不是实现了该抽象方法。

    79、(P204) 关于接口的说明:a) 使无关的类间具有相关性。由于接口中的抽象方法不一定要在继承树上的某个类来实现,这就为完全无关的几个类实现同样一组方法提供了一种有效的手段。换句话说,让这几个完全无关的类都具有接口所说明的功能,从而使无关的类间具有了相关性。     (P206) b) 接口类型和抽象类型虽然不能实例化创建自身的一个对象,但可以使用它们的引用变量作为一个方法的形参,也可以定义这样一个引用变量让它指向非抽象实现类或子类的对象。

    80、(P206) 内部类:是从JDK 1.1版本才开始添加的一种新的class类型。它是定义在另一个类体中的类,即把一个类的定义部分写在另一个类的内部。也称为“嵌套类”。封装内部类的类称为“外部类”,也称为“封装类”。     内部类的定义部分可以象成员变量一样写在所有方法体之外,此时可以成为“成员类”;内部类的定义部分还可以写在用一对大括号包围的块语句内,其中包括方法体,即可在外部类的一个方法体内定义一个内部类,并与成员类略有不同。(可见,内部类分为两种,一种是成员类,一种是在方法体内的内部类)

    81、(P206 - P210) 成员类:a) 外部类不能定义成私有类,而内部类不仅可以定义成公有、保护和友元等类,还可以定义成私有内部类。b) 当创建内部类的一个对象时,事先必须已存在一个作为它存在环境的外部类对象,故内部类的完整类名是:外部类名.内部类名 。当要在外部类的实例方法体以外的任何程序区段创建内部类的一个对象时,该对象所属类名必须使用该内部类的完整类名,并且,编译后所得的类文件名为:外部类名$内部类名.class 。   c) 当创建内部类的对象时,该外部类对象就是内部类对象的当前环境,从而确保了外部类和内部类是一个整体,使得内部类的方法也可以直接访问外部类的成员变量。   d) 内部类也是类的成员,因此,一个类的成员除了可以是变量和方法外,还可以是一个内部类(因此也称为成员类), 与成员变量一样,成员类(内部类)可用public、protected、private等访问控制符修饰。 e) 用static修饰的内部类称为“静态内部类”,它与静态成员变量类似,不隐含有指向封装它的外部类对象的引用变量。因此,静态内部类的方法只能访问外部类的静态成员变量(或称类成员变量),而不能访问外部类的实例成员变量。

    82、(P211 - P212) 方法体内的内部类:a) 与在方法体内定义的变量类似,在方法体内定义的内部类就不是外部类的成员。定义它的方法体就是它的作用域。离开该方法体就不能访问它,因此,可以说它对该方法是私有的。  b) 内部类所在的方法称为“封装方法”。 c) 这种内部类不能再用public、protected、private等访问控制符修饰,也不能把它声明为static 。   c) 在方法体内定义的自动变量必须用修饰符final定义成最终变量才能被内部类的方法访问,即在内部类的方法只能访问封装方法体中的final型自动变量。

    83、(P212 - P216) 匿名类:a) 在方法体内还可以定义匿名内部类,简称匿名类。 b) 这种匿名内部类在源代码中没有类名,声明和创建一个匿名类的格式为:      new Yyy() { 类体 }    c)   new Yyy() {类体}  只是一个表达式,它可以放到 return 语句中。如:return new Yyy{类体};  d) 该表达式还可以作为一个方法调用的实参,如:SomeMethod( new Yyy() { 类体 } );   e) 匿名类不能拥有构造方法,即编程者不能编写匿名类的构造方法,但系统会自动提供默认构造方法去完成新创建对象的初始化操作。   f) 匿名类是简单的小型class类型,一般只有几行易懂的代码,并放在一个方法体内。创建的匿名类对象通常用来作为方法的参数或者作为方法的返回值,这在AWT的事件驱动程序中广泛应用。

    84、(P217) 内部类的继承:a)若从含有内部类的外部类派生出一个子类,并在子类体内重新定义一个同名的内部类,但是由于子类的内部类的方法不能覆盖父类的内部类中的原型完全相同的方法,因此,这种结构使用价值不大。 h) 基于上条所述的原因,通常都是从内部类继承,子类只扩展了内部类,而没有扩展外部类,此时必须要给子类传递一个封装类(即内部类所在的外部类)的对象引用。例如:定义内部类OuterWithInner.InnerOne的子类InheritInner, 如下:  public class InheritInner extends OuterWithInner.InnerOne  { ...... }

    85、(P218) 对象引用的自动类型转换和造型: a) 在Java中通常用对象引用变量来代表对象,但实际上它们是两个实体。  b) 对象引用变量的类型转换类似于基本数据类型,也分为自动类型转换和强制类型转换,后者称为“造型”。

    86、(P218 - P220) 对象引用的自动类型转换: a) 当对象引用进行赋值运算时,当右值的对象引用与左值的对象引用类型不一致时,将进行自动类型转换,把右值的对象引用类型自动转换成左值的类型。 b) 引用变量允许自动类型转换的方向是沿着类层次结构的“上溯”(up)方向,继承链是由超类向下往子类继承,而引用变量的自动转换方向是逆流而上,由子类(包括间接子类)转换成超类才允许进行。  c) 基本数据类型自动转换的基本原则是“扩宽转换”,而对象引用的自动转换方向是继承链中的“上溯”方向。 f) 若对象引用作为方法的参数或返回值,当方法被调用时,则这些对象引用也将发生自动转换,且转换规则与上述赋值运算完全一样。g) 对象引用的自动转换与基本数据类型一样都是在编译时进行的。也就是说,编译时就可以发现自动转换是否正确。

    87、(P220 - P221) 对象引用的造型(Casting):  a) 对象引用的造型比基本数据类型的造型要复杂。首先,对象引用和它所指的对象是两个实体,因此,当一个类的对象不能改变时可以用不同类型的对象引用指向它;再者,它不仅要遵循编译期间的转换规则,还需遵循运行期间转换规则。    b) 编译期间的转换规则可归纳为如下三点:以如下赋值语句为例说明,
    OldType oldT = new OldType();      NewType newT = oldT;     (即 OldType类型的对象为右值,NewType类型的对象为左值)
    首先,当OldType和NewType都是class类型时,它们必须在同一条继承链上,即一个类是另一个类的子类。其次,当OldType和NewType都是数组时,它们必须是对象数组,即其元素必须都是对象引用类型而不能是基本数据类型。最后,接口的引用变量和任何非最终类的对象引用之间的相互造型在任何组合情况下都是可行的。  c) 运行期间的转换规则为: 首先,若NewType是一个class类型, 则被转换表达式的类(OldType)必须是NewType类型或者是它的子类。 再者,若NewType是一个接口,则被转换表达式的类(OldType)必须是NewType接口的实现类。

  • 相关阅读:
    ReflectionException: There is no getter for property named
    iframe发送post请求
    wget已安装但命令没找到
    linux性能观察命令
    ELK搭建
    python之中特性(attribute)与属性(property)有什么区别?
    Django中的日志详解
    创建fastdfs_nginx容器及nginx配置
    2. 顺序表 数据结构与算法(python)
    Ubuntu安装和卸载搜狗输入法
  • 原文地址:https://www.cnblogs.com/it_han_ku/p/481874.html
Copyright © 2011-2022 走看看