深耕JavaSe - 解析继承和多态
文章目录
- 1. 继承
- 1. 子类继承了父类,获得父类的全部Field和方法。
- 2. 子类继承了父类,额外增加新的Field和方法
- 3. 子类继承了父类,重写父类中的方法
- 4. super限定,在子类调用父类中被覆盖的方法
- 2. 多态
- 3. 引用变量的强制类型转换
- 4. 面试题
1. 继承
1. 子类继承了父类,获得父类的全部Field和方法。
子类Student类继承父类,将可以获得父类的全部Field和方法
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public static void main(String[] args) {Student student = new Student();student.name = "张三";student.age=18;// 调用父类中的show()方法student.show();}
}
2. 子类继承了父类,额外增加新的Field和方法
继承了父类中的属性和方法,同时新增一个show1()方法
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public static void show1(){System.out.println("调用了子类中的show1()方法");}public static void main(String[] args) {Student student = new Student();// 调用父类中的show()方法student.show();// 调用子类中的show1()方法student.show1();}
}
3. 子类继承了父类,重写父类中的方法
1、这种子类包含与父类同名方法的现象被称为方法重写,也被称为方法覆盖(Override)。可以说子类重写了父类的方法,也可以说子类覆盖了父类的方法。
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public void show(){System.out.println("调用了子类中的show()方法");}public static void main(String[] args) {Student student = new Student();// 调用了子类中的show()方法student.show();}
}
2、注意:方法的重写要遵循“两同两小一大”规则
(1) “两同”即方法名相同、形参列表相同;
(2) “两小”指的是子类方法返回值类型应比父类方法返回值类型更小或相等,子类方法声明抛出的异常类应比父类方法声明抛出的异常类更小或相等;
(3) “一大”指的是子类方法的访问权限应比父类方法的访问权限更大或相等;
(4) 尤其需要指出的是,覆盖方法和被覆盖方法要么都是类方法,要么都是实例方法,不能一个是类方法,一个是实例方法;
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {// 编译报错,因为父类中的show()方法不是static修饰的,子类就不能使用static修饰public static void show(){System.out.println("调用了子类中的show()方法");}
}
3、注意:如果父类方法具有private访问权限,则该方法对其子类是隐藏的,因此其子类无法访问该方法,也就是无法重写该方法。
如果子类中定义了一个与父类private方法具有相同的方法名、相同的形参列表、相同的返回值类型的方法,依然不是重写,只是在子类中重新定义了一个新方法。
public class Person {public int age;private void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {// show()方法是private方法,子类不可以访问该方法,因此可以添加static关键字public static void show(){System.out.println("调用了子类中的show()方法");}
}
4、注意:当子类覆盖了父类方法后,访问的便是子类中被覆盖的方法,将无法访问父类中被覆盖的方法。
4. super限定,在子类调用父类中被覆盖的方法
1、如果需要在子类方法中调用父类被覆盖的实例方法,则可使用super限定来调用父类被覆盖的实例方法。
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public void show(){System.out.println("调用了子类中的show()方法");}public void test(){// 调用了父类中的show()方法super.show();}public static void main(String[] args) {Student student = new Student();student.test();}
}
2、如果需要在子类方法中调用父类被覆盖的类方法,则可使用super限定来调用父类被覆盖的类方法。
public class Person {public int age;public static void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public static void show(){System.out.println("调用了子类中的show()方法");}public void test(){// 调用了父类中的show()方法Person.show();}public static void main(String[] args) {Student student = new Student();student.test();}
}
3、super是Java提供的一个关键字,super用于限定该对象调用它从父类继承得到的Field或实例方法。
正如this不能出现在static修饰的方法中一样,super也不能出现在static修饰的方法中。static修饰的方法是属于类的,该方法的调用者可能是一个类,而不是对象,因而super限定也就失去了意义。
public class Person {public int age;public void show(){System.out.println("调用了父类中的show()方法");}
}
public class Student extends Person {public void show(){System.out.println("调用了子类中的show()方法");}public void test(){// 调用了父类中的show()方法super.show();}public static void main(String[] args) {Student student = new Student();student.test();// 编译报错,因为super不能出现在static修饰的方法中super.show();}
}
4、如果子类定义了和父类同名的Field,则会发生子类Field隐藏父类Field的情形。
在正常情况下,子类里定义的方法默认会访问到子类中定义的Field,无法访问到父类中被隐藏的Field,在子类定义的实例方法中可以通过super来访问父类中被隐藏的Field
public class Person {public int age=5;
}
public class Student extends Person {private int age = 10;public void getOwner(){System.out.println(age);}public void getBase(){System.out.println(super.age);}public static void main(String[] args) {Student student = new Student();// 10student.getOwner();// 5student.getBase();}
}
如果在某个方法中访问名为age的Field,但没有显式指定调用者,则系统查找a的顺序为:
(1) 查找该方法中是否有名为age的局部变量;
(2) 查找当前类中是否包含名为age的Field;
(3) 查找age的直接父类中是否包含名为age的Field,依次上溯age的所有父类,直到java.lang.Object类,如果最终不能找到名为age的Field,则系统出现编译错误。
5、子类不会获得父类的构造器,但子类构造器里可以调用父类构造器的初始化代码
(1) 在一个构造器中调用另一个重载的构造器使用this调用来完成,在子类构造器中调用父类构造器使用super调用来完成;
(2) 如果在构造器中使用super,则super用于限定该构造器初始化的是该对象从父类继承得到的Field,而不是该类自己定义的Field;
public class Person {public String name;public int age;public Person(String name){this.name = name;}public Person(String name,int age){this.name = name;this.age = age;}
}
public class Student extends Person {private String color;// super调用的是其父类的构造器,而this调用的是同一个类中重载的构造器// 使用super调用父类构造器也必须出现在子类构造器执行体的第一行,所以this调用和super调用不会同时出现public Student(String name,int age){super(name);this.age = age;}public Student(String name,int age,String color){// 通过super调用父类构造器完成初始化过程this(name,age);this.color = color;}public static void main(String[] args) {Student student = new Student("张三",18,"红色");}
}
2. 多态
Java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。
public class Parent {public int book=10;public void test(){System.out.println("父类中的test()方法");}public void parent(){System.out.println("父类中的parent()方法");}
}
public class Sun extends Parent {public String book = "这是一本好书";public void test(){System.out.println("子类中的test方法");}public void sun(){System.out.println("子类中的sun方法");}public static void main(String[] args) {// 编译时类型和运行时类型一致,不存在多态Parent parent = new Parent();// 10System.out.println(parent.book);// 父类中的test()方法parent.test();// 父类中的parent()方法parent.parent();// 编译时类型和运行时类型一致,不存在多态Sun sun = new Sun();// 这是一本好书System.out.println(sun.book);// 子类中的test方法sun.test();// 子类中的sun方法sun.sun();// 编译时类型和运行时类型不一致,存在多态// p变量的编译时类型是Parent,而运行时类型是SunParent p = new Sun();// 对象的Field则不具备多态性// 10System.out.println(p.book);// 子类中的test方法p.test();// 父类中的parent()方法p.parent();// Parent类中没有sun()方法,编译报错p.sun();}
}
当把一个子类对象直接赋给父类引用变量时,例如上面的Parent p = new Sun();,这个p引用变量的编译时类型是Parent,而运行时类型是sun :
(1) Java允许把一个子类对象直接赋给一个父类引用变量,无须任何类型转换,这种被称为向上转型,向上转型由系统自动完成;
(2) 当调用该引用变量的test方法时,实际执行的是Sun类中覆盖后的test方法,这就是多态;当运行时调用该引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征,这就可能出现:相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,这就是多态。
(3) 与方法不同的是,对象的Field则不具备多态性,通过引用变量来访问其包含的实例Field时,系统总是试图访问它编译时类型所定义的Field,而不是它运行时类型所定义的Field;
3. 引用变量的强制类型转换
编写Java程序时,引用变量只能调用它编译时类型的方法,而不能调用它运行时类型的方法,如果需要让这个引用变量调用它运行时类型的方法,则必须把它强制类型转换成运行时类型。
(1) 基本类型之间的转换只能在数值类型之间进行,这里所说的数值类型包括整数型、字符型和浮点型。但数值类型和布尔类型之间不能进行类型转换。
(2) 引用类型之间的转换只能在具有继承关系的两个类型之间进行,如果是两个没有任何继承关系的类型,则无法进行类型转换,否则编译时就会出现错误。
考虑到进行强制类型转换时可能出现异常,因此进行类型转换之前应先通过instanceof运算符来判断是否可以成功转换。
(1) instanceof运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类或者接口,它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,则返回true,否则返回false;
(2) 在使用instanceof运算符时需要注意:instanceof运算符前面操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系,否则会引起编译错误;
(3) instanceof运算符的作用是:在进行强制类型转换之前,首先判断前一个对象是否是后一个类的实例,是否可以成功转换,从而保证代码更加健壮;
(4) instanceof和(type)是Java提供的两个相关的运算符,通常先用instanceof判断一个对象是否可以强制类型转换,然后再使用(type)运算符进行强制类型转换,从而保证程序不会出现错误;
public class Main {public static void main(String[] args) {Object object = "hello";if(object instanceof String){String s = (String) object;}}
}
4. 面试题
1、Java中实现多态的机制是什么?
Java中的多态靠的是父类或接口定义的引用变量可以指向子类或具体实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实例对象的方法,也就是内存里正在运行的那个对象的方法,而不是引用变量的类型中定义的方法。
2、谈谈你对多态的理解?
多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量到底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在程序运行期间才能决定。
因为在程序运行时才确定具体的类,这样,不用修改源代码,就可以让引用变量绑定到各种不同的对象上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
深耕JavaSe - 解析继承和多态相关推荐
- 【JavaSE】JavaSE之继承和多态
JavaSE继承和多态 一. 继承 1.1 为什么需要继承 1.2 继承概念 1.3 继承的语法 1.4 父类成员访问 1.5 super关键字 1.6 子类构造方法: 1.7 super和this ...
- 判断类型是否继承_【Java学习 | Javase】继承与多态
整理自:老师课件.<Java核心技术> 继承与多态 继承 概念 父类/超类 所有子集的公共域和公共方法的集合 子类 父类的特殊化,是对公共域和方法在功能.内涵方面的拓展和延伸 object ...
- java 继承与多态的区别_【转】 【JavaSE】继承与多态的理解与区别
抽象类的特点: A:抽象类和抽象方法必须用abstract关键字修饰 B:抽象类中不一定有抽象方法,但是有抽象方法的类必须定义为抽象类 C:抽象类不能实例化 因为它不是具体的. 抽象类有构造方法,但是 ...
- JavaSE面向对象:继承、多态、Super、Object类、重写、static、final、静态成员、懒汉式、饿汉式、单例设计模式、初始化块、抽象类、抽象方法、接口
感谢尚硅谷免费提供的视频 继承 ** 理解 ** 生活中的继承:子女继承了父母的财产或相貌或才华 java中的继承:一个类不用自己定义属性或方法,就已经具备了另一个类的属性和方法 把这种现象称为jav ...
- 杂货边角(7):C++继承和多态的符号表角度解析
面向对象设计核心的思想便是抽象.封装.继承.多态和接口.继承机制是面向对象设计过程中动态性和模块性的来源,而多态性则是很多功能灵活性的来源. 0. C++继承机制 面向对象设计核心是抽象的思维,但是& ...
- 类对接口的实现不叫继承_Java多态的实现机制是什么,看完你就知道(值得收藏)...
Java多态的实现机制是父类或接口定义的引用变量可以指向子类或实现类的实例对象,而程序调用的方法在运行期才动态绑定,就是引用变量所指向的具体实现对象的方法,也就是内存里正在运行的那个对象的方法,而不是 ...
- Python基础day09【面向对象(封装、继承、多态)、重写、私有权限】
视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] Python基础day09[面向对象(封装.继承.多态).重写.私有权限] Python基础day ...
- 春风桃李花开夜,秋雨梧桐叶落时——python面向对象三大特征(封装、继承、多态)
九重城阙烟尘生,千乘万骑西南行. 翠华摇摇行复止,西出都门百余里. 六军不发无奈何,宛转娥眉马前死. 花钿委地无人收,翠翘金雀玉搔头. 君王掩面救不得,回看血泪相和流. 黄埃散漫风萧索,云栈萦纡登剑阁 ...
- 学习笔记:C++进阶【继承、多态、二叉树进阶、map和set、哈希、C++11、异常、智能指针、特殊类设计、C++的类型转换】
文章目录 前言 一.继承 1. 继承的概念及定义 1.1 继承的概念 1.2 继承的定义 1.2.1 定义格式 1.2.2 继承关系和访问限定符 1.2.3 继承基类成员访问方式的变化 2. 基类和派 ...
最新文章
- bootstrap上传文件美化
- 清华大学:人工智能之知识图谱(附PPT)
- Atitit.js模块化 atiImport 的新特性javascript import
- SAP Spartacus B2B 页面信息提示图标的弹出窗口显示实现逻辑
- 让我们来谈谈合并排序算法
- 由遍历序列构造二叉树
- QTTabBar 安装使用记录
- it职位简称_IT行业常见职位英文缩写
- Mac屏保不生效问题的解决
- Android 键盘属性
- 查询数据库表字段属性
- 线性颜色空间与伽马颜色空间
- linux mkdir命令用法,linux里面的mkdir命令
- LIGO找到首个超越广义相对论的证据?
- 【电脑使用】美化你的Windows
- 放大电路的静态工作点
- Object类是什么?
- HTML5中将中文表单验证默认提示语句改为英文!
- windows下oracle10的日志,在Windows上安装Oracle10gR2
- android系统弹窗,Android桌面弹窗实现总结
热门文章
- SSH通过“运维密码”小程序实现 SSH 双因子认证
- 【领峰交易争霸赛·第二季】4月27日启动报名,实盘PK,每天赢奖金
- 搬砖工php什么意思,我要去搬砖了是什么意思什么梗? 搬砖的几种含义了解一下...
- 【0基础学python必看】python行业调研分析——现状+优势+薪资+发展
- 股票和期货有什么区别(期货投机与股票投机的区别)
- dedecms arclist php标签,织梦标签代码Arclist标记怎么用
- Android service学习笔记
- Android的SharePreferences存储的案例(qq账号存储)
- 车牌区域提取(定位)综述及各种算法的优缺点
- 亚服服务器维修,亚服游戏服务器地址