【Java基本功】一文了解Java中继承、封装、多态的细节
本节主要介绍Java面向对象三大特性:继承 封装 多态,以及其中的原理。
本文会结合虚拟机对引用和对象的不同处理来介绍三大特性的原理。
继承
Java中的继承只能单继承,但是可以通过内部类继承其他类来实现多继承。
public class Son extends Father{public void go () {System.out.println("son go");}public void eat () {System.out.println("son eat");}public void sleep() {System.out.println("zzzzzz");}public void cook() {//匿名内部类实现的多继承new Mother().cook();//内部类继承第二个父类来实现多继承Mom mom = new Mom();mom.cook();}private class Mom extends Mother {@Overridepublic void cook() {System.out.println("mom cook");}}}
封装
封装主要是因为Java有访问权限的控制。public > protected > package = default > private。封装可以保护类中的信息,只提供想要被外界访问的信息。
类的访问范围
A、public 包内、包外,所有类中可见B、protected 包内所有类可见,包外有继承关系的子类可见(子类对象可调用)C、(default)表示默认,不仅本类访问,而且是同包可。D、private 仅在同一类中可见
多态
多态一般可以分为两种,一个是重写,一个是重载。
重写是由于继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。重载是因为一个同名方法可以传入多个参数组合。注意,同名方法如果参数相同,即使返回值不同也是不能同时存在的,编译会出错。从jvm实现的角度来看,重写又叫运行时多态,编译时看不出子类调用的是哪个方法,但是运行时操作数栈会先根据子类的引用去子类的类信息中查找方法,找不到的话再到父类的类信息中查找方法。而重载则是编译时多态,因为编译期就可以确定传入的参数组合,决定调用的具体方法是哪一个了。
向上转型和向下转型:
public static void main(String[] args) {Son son = new Son();//首先先明确一点,转型指的是左侧引用的改变。//father引用类型是Father,指向Son实例,就是向上转型,既可以使用子类的方法,也可以使用父类的方法。//向上转型,此时运行father的方法Father father = son;father.smoke();//不能使用子类独有的方法。// father.play();编译会报错father.drive();//Son类型的引用指向Father的实例,所以是向下转型,不能使用子类非重写的方法,可以使用父类的方法。//向下转型,此时运行了son的方法Son son1 = (Son) father;//转型后就是一个正常的Son实例son1.play();son1.drive();son1.smoke();//因为向下转型之前必须先经历向上转型。//在向下转型过程中,分为两种情况://情况一:如果父类引用的对象如果引用的是指向的子类对象,//那么在向下转型的过程中是安全的。也就是编译是不会出错误的。//因为运行期Son实例确实有这些方法Father f1 = new Son();Son s1 = (Son) f1;s1.smoke();s1.drive();s1.play();//情况二:如果父类引用的对象是父类本身,那么在向下转型的过程中是不安全的,编译不会出错,//但是运行时会出现java.lang.ClassCastException错误。它可以使用instanceof来避免出错此类错误。//因为运行期Father实例并没有这些方法。Father f2 = new Father();Son s2 = (Son) f2;s2.drive();s2.smoke();s2.play();//向下转型和向上转型的应用,有些人觉得这个操作没意义,何必先向上转型再向下转型呢,不是多此一举么。其实可以用于方法参数中的类型聚合,然后具体操作再进行分解。//比如add方法用List引用类型作为参数传入,传入具体类时经历了向下转型add(new LinkedList());add(new ArrayList());//总结//向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法//并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错。//若安全则继续执行方法。}public static void add(List list) {System.out.println(list);//在操作具体集合时又经历了向上转型// ArrayList arr = (ArrayList) list;// LinkedList link = (LinkedList) list;}
总结: 向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪个方法。并且在传入方法时会自动进行转型(有需要的话)。运行期将引用指向实例,如果是不安全的转型则会报错,若安全则继续执行方法。
编译期的静态分派
其实就是根据引用类型来调用对应方法。
public static void main(String[] args) {Father father = new Son();静态分派 a= new 静态分派();//编译期确定引用类型为Father。//所以调用的是第一个方法。a.play(father);//向下转型后,引用类型为Son,此时调用第二个方法。//所以,编译期只确定了引用,运行期再进行实例化。a.play((Son)father);//当没有Son引用类型的方法时,会自动向上转型调用第一个方法。a.smoke(father);//}public void smoke(Father father) {System.out.println("father smoke");}public void play (Father father) {System.out.println("father");//father.drive();}public void play (Son son) {System.out.println("son");//son.drive();}
方法重载优先级匹配
public static void main(String[] args) {方法重载优先级匹配 a = new 方法重载优先级匹配();//普通的重载一般就是同名方法不同参数。//这里我们来讨论当同名方法只有一个参数时的情况。//此时会调用char参数的方法。//当没有char参数的方法。会调用int类型的方法,如果没有int就调用long//即存在一个调用顺序char -> int -> long ->double -> ..。//当没有基本类型对应的方法时,先自动装箱,调用包装类方法。//如果没有包装类方法,则调用包装类实现的接口的方法。//最后再调用持有多个参数的char...方法。a.eat('a');a.eat('a','c','b');}public void eat(short i) {System.out.println("short");}public void eat(int i) {System.out.println("int");}public void eat(double i) {System.out.println("double");}public void eat(long i) {System.out.println("long");}public void eat(Character c) {System.out.println("Character");}public void eat(Comparable c) {System.out.println("Comparable");}public void eat(char ... c) {System.out.println(Arrays.toString(c));System.out.println("...");}// public void eat(char i) {// System.out.println("char");// }
【Java基本功】一文了解Java中继承、封装、多态的细节的更多相关文章
- OOP面向对象 三大特征 继承封装多态
OOP面向对象 ----三大特征 继承封装多态 面向对象(Object Oriented,OO)是软件开发方法.面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统.交互式界面.应用结构 ...
- [转]Java中继承、多态、重载和重写介绍
什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上 ...
- Java面向对象理解_代码块_继承_多态_抽象_接口
面线对象: /* 成员变量和局部变量的区别? A:在类中的位置不同 成员变量:在类中方法外 局部变量:在方法定义中或者方法声明上 B:在内存中的位置不同 成员变量:在堆内存 局部变量:在栈内存 C:生 ...
- Java类与类的关系、继承与多态、重写与重载
Java类与类的关系 (1)is-a包括了 继承,实现关系 (2)has-a包括了 关联,聚合,组合关系 (3)use-a包括了 依赖关系 实现关系: 实现指的是一个class类实现interface ...
- Java面向对象笔记 • 【第3章 继承与多态】
全部章节 >>>> 本章目录 3.1 包 3.1.1 自定义包 3.1.2 包的导入 3.1.3 包的访问权限 3.1.4 实践练习 3.2 继承 3.2.1 继承概述 3 ...
- python中继承和多态
继承和多态 继承 引入继承 我们有这样一个需求 模仿英雄联盟定义两个英雄类 1.英雄要有昵称.攻击力.生命值属性 2.实例化出两个英雄对象 3.英雄之间可以互殴,被殴打的一方掉血,血量小于0则判断为死 ...
- C#中继承和多态
1.继承的概念 继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用已存在的类的功能. 为了提高软件模块的可复用性和可扩充性,以便提高软件的开发效率,我们总 ...
- c语言中继承和多态的简单实现
C语言本身是不支持继承和多态的,但其实在 C 的世界里,有一套非常有名的面向对象的框架,用的也非常广,那就是 GObject,它是整个图形界面开发库 GTK 的基石,在IBM developerWor ...
- Java中继承与多态
Java类的继承继承的语法结构: [修饰符列表] class 子类名 extends 父类名{ 类体; }子类就是当前这个类,父类就是我们要复用的那个类java中只支持单继承 ...
- java中继承和多态的理解
继承的概念 继承是java面向对象编程技术的一块基石,因为它允许创建分等级层次的类. 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父 ...
随机推荐
- Linux知识扩展二:lsof命令
转:https://www.cnblogs.com/the-study-of-linux/p/5501593.html 1. lsof :list open file 显示linux下打开的文件信息. ...
- stark组件开发之添加功能实现
添加功能,还是使用, form 组件来完成! 并且 完成添加之后,需要保留原搜索条件. def memory_url(self): '''用于反向生成url, 并且携带,get请求的参数,跳转到下一 ...
- vue-if和v-show区别
vue-if和vue-show都是对条件进行判断,一直不明白他们的区别,知道看到了官方文档中的解释: v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和 ...
- [JAVA]JAVA章3 如何获取及查看DUMP文件
一.dump基本概念 在故障定位(尤其是out of memory)和性能分析的时候,经常会用到一些文件来帮助我们排除代码问题.这些文件记录了JVM运行期间的内存占用.线程执行等情况,这就是我们常说的 ...
- sqlserver 日志查询
转载地址:https://www.cnblogs.com/davidhou/p/7890966.html
- Mysql知识点个人整理
1.概念 数据库:保存有组织的数据的容器. 表: 某种特定类型数据的结构化清单 模式:关于数据库和表的布局和特性的信息?(有时指数据库) 主键: primary key 一个列或一组列,其值能唯一区分 ...
- 73.解决Xcode10 library not found for -lstdc++ 找不到问题
Xcode10 彻底废除了libstdc++,相关文件libstdc++.6.0.9.dylib.libstdc++.6.dylib.libstdc++.dylib.libstdc++.6.0.9.t ...
- javascript的常用事件
- vue在element-ui的对话框的编辑控件回车时让焦点跳到下一控件
网上找的回车录入焦点前往一下控件的方式普遍比较复杂,自己不想用.学习了一个下午后似乎搞定.先帖一段代码,以后有时间解释,也请大家指教.利用下面的代码注册自己的v-enterToNext指令,并在el- ...
- EF6学习笔记(四) 弹性连接及命令拦截调试
EF6学习笔记总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 本章原文地址:Connection Resiliency and Command Interception 原文 ...