0022 Java学习笔记-面向对象-继承、多态、组合
继承的特点
- 单继承:每个子类最多只有一个直接父类,注意是直接父类,间接父类个数不限
- 注意父类的概念:A-->B-->C-->D,在这里,ABC都是D的父类,C是D的直接父类,AB是D的间接父类
- 父类和子类是一般和特殊的关系;子类扩展了父类,子类是一种特殊的父类
- Object是所有类的直接或间接父类;定义一个类时,若没有直接指定父类,则默认继承Object类
子类从父类继承了哪些要素
- 子类不继承父类的构造方法,但是总要调用父类的构造方法
- 子类继承了父类的实例变量和实例方法、类变量和类方法,当然前提是没有被private修饰
- 父类中被private修饰的成员,不会被子类继承
- 父类中用final修饰的方法,子类不能重写
方法的重写override
- 子类和父类拥有相同的方法签名,叫做子类重写了父类的方法
- 两同两小一大原则:
- 两同:方法名相同,形参列表相同
- 两小:子类方法的返回值跟父类的相等或更小;子类方法抛出的异常要跟父类抛出的相等或更小
- 一大:子类方法的访问权限要跟父类的相等或更大
- static:子类方法要跟父类方法一致,要么是类方法,要么是实例方法,二者不能不一致
- 方法重写后,子类对象将无法访问父类的方法,但可以在子类方法中调用父类的方法:super.实例方法,父类名.类方法
- 如果父类方法是private修饰,则子类不能重写该方法;如果子类拥有一个跟父类private方法相同签名的方法,这也不是重写,这是子类新添加的方法,与父类的无关
- 子类方法可能会和父类的方法发生重载
- 父类中用final修饰的方法,子类不能重写
super关键字
- 在子类中,用super关键字调用父类的实例变量或实例方法
- super和static不能同时用来修饰方法;就像this不能和static不能同时修饰方法一样
- 子类从父类继承了一个变量,又再定义了一个变量,而且同名,此时可以用super.变量名或者父类名.变量名来访问父类的这个变量
变量的查找顺序
- 子类方法访问了一个变量,没有显式指定调用者的情况下,按以下顺序查找:
- 当前方法中,是否有同名的局部变量
- 当前类中,是否有同名的成员变量
- 直接父类中,是否有
- 逐级网上追溯,如果最终没有找到,那么提示编译出错
super调用父类构造器
- 子类虽然不会继承父类的构造器,但总是会调用父类的构造器。调用同一个类的构造器用this,调用父类的用super
- 显式调用:super调用语句写在在构造方法的第一行,因为this也要写在第一行,因此super和this不会同时出现
- 间接调用:子类方法的第一行写的是this,被调用的构造器还得调用父类的构造器
- 隐式调用:无super无this,系统默认调用父类的无参构造
- 子类继承父类,总会一级一级的往上调用父类构造器,直到调用Object的,并且是找到顶部父类构造器后,开始往下一层一层执行
- 比如下面的代码,继承关系:A-->B-->C-->D
public class Test{
public static void main(String[] args) {
D d=new D();
}
}
class D extends C{
D(){
System.out.println("D类构造器");
}
}
class C extends B{
C(){
System.out.println("C类构造器");
}
}
class B extends A{
B(){
System.out.println("B类构造器");
}
}
class A{
A(){
System.out.println("A类构造器");
}
}
输出:
A类构造器
B类构造器
C类构造器
D类构造器
- 如果父类没有无参构造,子类又需要调用父类的无参构造,那么不能通过编译
多态Polymorphism
- 简单的说,多态就是:在一个金字塔式的继承体系中,创建底部子类对象时,用顶端的父类类型指向这些底部的子类对象,通过相同类型的引用变量调用同一个方法时,会出现不同的结果
- 多态源于:继承+父类型的引用指向子类型的对象+方法的重写
- 引用变量有两个类型,一个是编译时类型,一个是运行时类型
- 向上转型:父类型引用指向子类型对象,向上转型由系统自动完成
- 向上转型的情况下:通过父类型的引用可以调用子类重写了的方法,但不能访问父类中没有子类中才有的实例变量,也就是说实例变量不具有多态性
instanceof与强制类型转换
- 基本类型有强制类型转换,比如(double)16;引用类型也存在强制类型转换
- 比如存在以下继承链:A-->B-->C-->D-->E-->F,B b=new D(),此时用B类型指向D对象,此时可以把b变量转为ACD类型,但不能转为EF类型,抛出异常ClassCastException
- 进行强制类型转换之前,应先用instanceof进行判断能不能转,避免抛出异常
- X变量 instanceof Y类型:判断X变量能不能转为Y类型,可能出现三种情况:
- true表示可以转,意味着X变量指向的对象的类型,是Y类型或者Y的子类型;
- false表示不可以转,意味着X变量的类型与Y类型存在父子继承关系,不可能是子父关系,X变量指向的对象的类型与Y类型没有父子或子父关系,二者都是X变量类型的子类型;
- 编译不通过,表示X和Y没有父子或者子父继承关系
继承与组合
- 继承可以实现代码的复用,但破坏了封装;组合也可以实现代码的复用
- 设计父类遵循的原则:
- 尽量用private隐藏父类的内部数据,不让子类直接访问父类的成员变量
- 不要让子类随意访问、修改父类方法。父类辅助性的工具方法,用private修饰;需要让外部调用的方法,用public;不希望子类重写的方法用final修饰;希望子类重写而不希望外部访问则用protected
- 不要在父类构造器中调用可能被子类重写的方法,后果很严重
- 设计继承的原则:
- 子类需要增加额外的属性,而不是属性的改变
- 子类需要增加自己独有的功能或行为,可以增加新方法,或者重写父类方法
- 不要光出于代码复用的目的设计继承,而要看实际情况,父类和子类是否有"has-a"的关系
- 不想让一个类被继承:
- final:用final修饰该类为最终类,不能被继承
- private:用private修饰该类的所有构造方法,这样子类就无法调用该类的构造器,就不能继承了,另外应提供一个静态方法,用来返回该类的对象
- 组合也能实现代码的复用
- A类复用B类的方法
- A类中创建B类的对象,并用private修饰
- 在A类方法中调用B类对象的方法
- 组合还是继承:
- 继承:子类与父类是"is-a"关系,具体与抽象、特殊与一般的关系
- 组合:新类与旧类是"has-a"关系,整体与局部的关系
其他:
- 对于子类从父类继承了一个变量,又定义了一个同名变量的情况下,在创建子类对象时,为这两个变量都分配了内存,只是父类变量被隐藏
0022 Java学习笔记-面向对象-继承、多态、组合的更多相关文章
- 0030 Java学习笔记-面向对象-垃圾回收、(强、软、弱、虚)引用
垃圾回收特点 垃圾:程序运行过程中,会为对象.数组等分配内存,运行过程中或结束后,这些对象可能就没用了,没有变量再指向它们,这时候,它们就成了垃圾,等着垃圾回收程序的回收再利用 Java的垃圾回收机制 ...
- 0028 Java学习笔记-面向对象-Lambda表达式
匿名内部类与Lambda表达式示例 下面代码来源于:0027 Java学习笔记-面向对象-(非静态.静态.局部.匿名)内部类 package testpack; public class Test1{ ...
- 0025 Java学习笔记-面向对象-final修饰符、不可变类
final关键字可以用于何处 修饰类:该类不可被继承 修饰变量:该变量一经初始化就不能被重新赋值,即使该值跟初始化的值相同或者指向同一个对象,也不可以 类变量: 实例变量: 形参: 注意可以修饰形参 ...
- 0013 Java学习笔记-面向对象-static、静态变量、静态方法、静态块、单例类
static可以修饰哪些成员 成员变量---可以修饰 构造方法---不可以 方法---可以修饰 初始化块---可以修饰 内部类(包括接口.枚举)---可以修饰 总的来说:静态成员不能访问非静态成员 静 ...
- 程序设计基础·Java学习笔记·面向对象(下)
Java程序设计基础之面向对象(下) (补充了上的一些遗漏的知识,同时加入了自己的笔记的ヾ(•ω•`)o) (至于为什么分P,啊大概是为了自己查笔记方便(?)应该是("` 3′") ...
- Java基础笔记-抽象,继承,多态
抽象类: abstract修饰 抽象方法必须定义在抽象类中,抽象类不能创建对象. 在抽象方法中可以不定义抽象方法,作用是:让该类不能建立对象. 特点是: 1.定义在抽象类中 2.方法和类都用abstr ...
- 0021 Java学习笔记-面向对象-包、构造器
封装 面向对象的三大特征: 封装 继承 多态 封装: 将对象的状态信息隐藏,不允许外部程序直接访问 通过该类提供的方法来访问和操作 有啥用: 隐藏类的实现细节 在方法中加入控制逻辑,限制对成员变量的不 ...
- Java 学习笔记(6)——继承
之前说过了Java中面向对象的第一个特征--封装,这篇来讲它的第二个特征--继承.一般在程序设计中,继承是为了减少重复代码. 继承的基本介绍 public class Child extends Pa ...
- 1.8(java学习笔记)继承与方法的重写
继承 在java中可以通过继承提高代码的复用率. 例如A继承了B,就可以是 例如,首先有一个类似Person,这个类中有有一些属性和方法,我们再新建一个Student类,其中有一部分属性和方法与Per ...
随机推荐
- 本地电脑安装和配置Redis操作客户端
下载需要的文件:http://pan.baidu.com/s/1gdfQePl 把这个下载下来解压就可以了,如图所示 第一步(配置本地服务) 点击run这个DOS执行命令 因为是自己的电脑测试 ...
- Java 读取Properties文件时应注意的路径问题
1. 使用Class的getResourceAsStream()方法读取Properties文件(资源文件)的路径问题: InputStream in = this.getClass().getRe ...
- 互联网背景时代下的大机遇,为什么用nosql
1.单机MySQL的美好年代 在90年代,一个网站的访问量一般都不大,用单个数据库完全可以轻松应付.在那个时候,更多的都是静态网页,动态交互类型的网站不多. 上述架构下,我们来看看数据存储的瓶颈是什么 ...
- Python程序员的进化史
各种程序员所写的阶乘算法代码 # -*- coding: utf-8 -*- #新手程序员(递归) def factorial(x): if x == 0: return 1 else: return ...
- Scalaz(7)- typeclass:Applicative-idomatic function application
Applicative,正如它的名称所示,就是FP模式的函数施用(function application).我们在前面的讨论中不断提到FP模式的操作一般都在管道里进行的,因为FP的变量表达形式是这样 ...
- php中数组遍历改值
<?php $arr = array(100, 99, 88, 77, 55, 66); //方法1 foreach ($arr as &$v) { $v = 2; } print_r( ...
- jackson中JSON字符串节点遍历和修改
有些场景下,在实现一些基础服务和拦截器的时候,我们可能需要在不知道JSON字符串所属对象类型的情况下,对JSON字符串中的某些属性进行遍历和修改,比如,设置或查询一些报文头字段. 在jackson中, ...
- Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
现在如果想打造一款专业的App,UI的设计和操作的简便性相当重要.UI设计可以借助Photoshop或者AI等设计工具,之前了解到WPF设计工具Expression Blend可以直接导入PSD文件或 ...
- 原型prototype
JS对象的比较 由于JS是解释执行的语言,那么代码中出现函数与对象如果重复执行,会创建多个副本 创建一个Person构造函数,要求有name,age,gender,sayHello 代码如下: fun ...
- SharePoint 创建模版页
[1]需要安装SharePoint Designer 最新版编辑工具 [2]我用的是SharePoint Server 2013 如果是Office 请匹配寻找 1.创建母版页面 打开右上角-网站设 ...