夯实Java基础系列1:Java面向对象三大特性(基础篇)

本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到个人仓库里查看html

https://github.com/h2pl/Java-Tutorialjava

喜欢的话麻烦点下Star哈android

文章首发于个人我的博客:git

www.how2playlife.com程序员

本文是微信公众号【Java技术江湖】的《夯实Java基础系列博文》其中一篇,本文部份内容来源于网络,为了把本文主题讲得清晰透彻,也整合了不少我认为不错的技术博客内容,引用其中了一些比较好的博客文章,若有侵权,请联系做者。 该系列博文会告诉你如何从入门到进阶,一步步地学习Java基础知识,并上手进行实战,接着了解每一个Java知识点背后的实现原理,更完整地了解整个Java技术体系,造成本身的知识框架。为了更好地总结和检验你的学习成果,本系列文章也会提供每一个知识点对应的面试题以及参考答案。github

若是对本系列文章有什么建议,或者是有什么疑问的话,也能够关注公众号【Java技术江湖】联系做者,欢迎你参与本系列博文的创做和修订。面试

<!-- more -->算法

Java面向对象三大特性(基础篇)

面向对象简称 OO(Object Oriented),20 世纪 80 年代之后,有了面向对象分析(OOA)、 面向对象设计(OOD)、面向对象程序设计(OOP)等新的系统开发方式模型的研究。编程

对语言来讲,一切皆是对象。把现实世界中的对象抽象地体如今编程世界中,一个对象表明了某个具体的操做。一个个对象最终组成了完整的程序设计,这些对象能够是独立存在的,也能够是从别的对象继承过来的。对象之间经过相互做用传递信息,实现程序开发。segmentfault

对象的概念

Java 是面向对象的编程语言,对象就是面向对象程序设计的核心。所谓对象就是真实世界中的实体,对象与实体是一一对应的,也就是说现实世界中每个实体都是一个对象,它是一种具体的概念。对象有如下特色:

  • 对象具备属性和行为。
  • 对象具备变化的状态。
  • 对象具备惟一性。
  • 对象都是某个类别的实例。
  • 一切皆为对象,真实世界中的全部事物均可以视为对象。

面向对象和面向过程的区别

  • 面向过程: 一种较早的编程思想,顾名思义就是该思想是站着过程的角度思考问题,强调的就是功能行为,功能的执行过程,即前后顺序,而每个功能咱们都使用函数(相似于方法)把这些步骤一步一步实现。使用的时候依次调用函数就能够了。

  • 面向过程的设计: 最小的程序单元是函数,每一个函数负责完成某一个功能,用于接受输入数据,函数对输入数据进行处理,而后输出结果数据,整个软件系统由一个个的函数组成,其中做为程序入口的函数称之为主函数,主函数依次调用其余函数,普通函数之间能够相互调用,从而实现整个系统功能。   面向过程最大的问题在于随着系统的膨胀,面向过程将没法应付,最终致使系统的崩溃。为了解决这一种软件危机,咱们提出面向对象思想。

  • 面向过程的缺陷: 是采用指定而下的设计模式,在设计阶段就须要考虑每个模块应该分解成哪些子模块,每个子模块又细分为更小的子模块,如此类推,直到将模块细化为一个个函数。

  • 存在的问题

    ​ 设计不够直观,与人类的思惟习惯不一致 系统软件适应新差,可拓展性差,维护性低

  • 面向对象:

    ​ 一种基于面向过程的新编程思想,顾名思义就是该思想是站在对象的角度思考问题,咱们把多个功能合理放到不一样对象里,强调的是具有某些功能的对象。

      具有某种功能的实体,称为对象。面向对象最小的程序单元是:类。面向对象更加符合常规的思惟方式,稳定性好,可重用性强,易于开发大型软件产品,有良好的可维护性。

  在软件工程上,面向对象可使工程更加模块化,实现更低的耦合和更高的内聚。

面向对象的三大核心特性简介

面向对象开发模式更有利于人们开拓思惟,在具体的开发过程当中便于程序的划分,方便程序员分工合做,提升开发效率。

该开发模式之因此使程序设计更加完善和强大,主要是由于面向对象具备继承、封装和多态 3 个核心特性。

一、继承的概念

继承是java面向对象编程技术的一块基石,由于它容许建立分等级层次的类。

继承就是子类继承父类的特征和行为,使得子类对象(实例)具备父类的实例域和方法,或子类从父类继承方法,使得子类具备父类相同的行为。

img

兔子和羊属于食草动物类,狮子和豹属于食肉动物类。

食草动物和食肉动物又是属于动物类。

因此继承须要符合的关系是:is-a,父类更通用,子类更具体。

虽然食草动物和食肉动物都是属于动物,可是二者的属性和行为上有差异,因此子类会具备父类的通常特性也会具备自身的特性。

二、Java 多态


多态是同一个行为具备多个不一样表现形式或形态的能力。

多态就是同一个接口,使用不一样的实例而执行不一样操做,如图所示:

img

多态性是对象多种表现形式的体现。

现实中,好比咱们按下 F1 键这个动做:

  • 若是当前在 Flash 界面下弹出的就是 AS 3 的帮助文档;
  • 若是当前在 Word 下弹出的就是 Word 帮助;
  • 在 Windows 下弹出的就是 Windows 帮助和支持。

同一个事件发生在不一样的对象上会产生不一样的结果。

三、Java 封装


在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。

封装能够被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

要访问该类的代码和数据,必须经过严格的接口控制。

封装最主要的功能在于咱们能修改本身的实现代码,而不用修改那些调用咱们代码的程序片断。

适当的封装可让程式码更容易理解与维护,也增强了程式码的安全性。

面向对象编程三大特性详解

面向对象编程是利用 类和对象编程的一种思想。万物可归类,类是对于世界事物的高度抽象 ,不一样的事物之间有不一样的关系 ,一个类自身与外界的封装关系,一个父类和子类的继承关系, 一个类和多个类的多态关系。万物皆对象,对象是具体的世界事物,面向对象的三大特征封装,继承,多态,封装,封装说明一个类行为和属性与其余类的关系,低耦合,高内聚;继承是父类和子类的关系,多态说的是类与类的关系。

1、继承

一、继承的概念

如同生活中的子女继承父母拥有的全部财产,程序中的继承性是指子类拥有父类数据结构的方法和机制,这是类之间的一种关系;继承只能是单继承。

例如定义一个语文老师类和数学老师类,若是不采用继承方式,那么两个类中须要定义的属性和方法如图 1 所示。

图1 语文老师类和数学老师类中的属性和方法

从图 1 可以看出,语文老师类和数学老师类中的许多属性和方法相同,这些相同的属性和方法能够提取出来放在一个父类中,这个父类用于被语文老师类和数学老师类继承。固然父类还能够继承别的类,如图 2 所示。

图2 父类继承示例图

总结图 2 的继承关系,能够用归纳的树形关系来表示,如图 3 所示。

图3 类继承示例图

从图 3 中能够看出,学校主要人员是一个大的类别,老师和学生是学校主要人员的两个子类,而老师又能够分为语文老师和数学老师两个子类,学生也能够分为班长和组长两个子类。

使用这种层次形的分类方式,是为了将多个类的通用属性和方法提取出来,放在它们的父类中,而后只须要在子类中各自定义本身独有的属性和方法,并以继承的形式在父类中获取它们的通用属性和方法便可。

 继承是类与类的一种关系,是一种“is a”的关系。好比“狗”继承“动物”,这里动物类是狗类的父类或者基类,狗类是动物类的子类或者派生类。以下图所示:

img

注: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 {
@Override
public void cook() {
System.out.println("mom cook");
}
}
}

二、继承的好处

 子类拥有父类的全部属性和方法(除了private修饰的属性不能拥有)从而实现了实现代码的复用; 

三、语法规则

img


A、方法的重写

 子类若是对继承的父类的方法不满意(不适合),能够本身编写继承的方法,这种方式就称为方法的重写。当调用方法时会优先调用子类的方法。

 重写要注意:

  a、返回值类型

  b、方法名

  c、参数类型及个数

 都要与父类继承的方法相同,才叫方法的重写。

 重载和重写的区别:

  方法重载:在同一个类中处理不一样数据的多个相同方法名的多态手段。

  方法重写:相对继承而言,子类中对父类已经存在的方法进行区别化的修改。


B、继承的初始化顺序

  一、初始化父类再初始化子类

  二、先执行初始化对象中属性,再执行构造方法中的初始化。

 基于上面两点,咱们就知道实例化一个子类,java程序的执行顺序是:

 父类对象属性初始化---->父类对象构造方法---->子类对象属性初始化--->子类对象构造方法   

 下面有个形象的图:

img


C、final关键字

 使用final关键字作标识有“最终的”含义。

  1. final 修饰类,则该类不容许被继承。
  2. final 修饰方法,则该方法不容许被覆盖(重写)
  3. final 修饰属性,则该类的该属性不会进行隐式的初始化,因此 该final 属性的初始化属性必须有值,或在**构造方法中赋值(但只能选其一,且必须选其一,由于没有默认值!),**且初始化以后就不能改了,只能赋值一次
  4. final 修饰变量,则该变量的值只能赋一次值,在声明变量的时候才能赋值,即变为常量

D、super关键字

 在对象的内部使用,能够表明父类对象。

  一、访问父类的属性:super.age

   二、访问父类的方法:super.eat()

 super的应用:

 首先咱们知道子类的构造的过程中必须调用父类的构造方法。其实这个过程已经隐式地使用了咱们的super关键字。

 这是由于若是子类的构造方法中没有显示调用父类的构造方法,则系统默认调用父类无参的构造方法。

 那么若是本身用super关键字在子类里调用父类的构造方法,则必须在子类的构造方法中的第一行

 要注意的是:若是子类构造方法中既没有显示调用父类的构造方法,而父类没有无参的构造方法,则编译出错。

(补充说明,虽然没有显示声明父类的无参的构造方法,系统会自动默认生成一个无参构造方法,可是,若是你声明了一个有参的构造方法,而没有声明无参的构造方法,这时系统不会动默认生成一个无参构造方法,此时称为父类有没有无参的构造方法。)


2、封装

一、封装的概念

封装是将代码及其处理的数据绑定在一块儿的一种编程机制,该机制保证了程序和数据都不受外部干扰且不被误用。封装的目的在于保护信息,使用它的主要优势以下。

  • 保护类中的信息,它能够阻止在外部定义的代码随意访问内部代码和数据。
  • 隐藏细节信息,一些不须要程序员修改和使用的信息,好比取款机中的键盘,用户只须要知道按哪一个键实现什么操做就能够,至于它内部是如何运行的,用户不须要知道。
  • 有助于创建各个系统之间的松耦合关系,提升系统的独立性。当一个系统的实现方式发生变化时,只要它的接口不变,就不会影响其余系统的使用。例如 U 盘,无论里面的存储方式怎么改变,只要 U 盘上的 USB 接口不变,就不会影响用户的正常操做。
  • 提升软件的复用率,下降成本。每一个系统都是一个相对独立的总体,能够在不一样的环境中获得使用。例如,一个 U 盘能够在多台电脑上使用。

Java 语言的基本封装单位是类。因为类的用途是封装复杂性,因此类的内部有隐藏实现复杂性的机制。Java 提供了私有和公有的访问模式,类的公有接口表明外部的用户应该知道或能够知道的每件东西,私有的方法数据只能经过该类的成员代码来访问,这就能够确保不会发生不但愿的事情。

二、封装的优势

在面向对象程式设计方法中,封装(英语:Encapsulation)是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。

封装能够被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。

要访问该类的代码和数据,必须经过严格的接口控制。

封装最主要的功能在于咱们能修改本身的实现代码,而不用修改那些调用咱们代码的程序片断。

适当的封装可让程式码更容易理解与维护,也增强了程式码的安全性。

封装的优势

  1. 良好的封装可以减小耦合。
  2. 类内部的结构能够自由修改。
  3. 能够对成员变量进行更精确的控制。
  4. 隐藏信息,实现细节。

Java 封装,说白了就是将一大坨公共通用的实现逻辑玩意,装到一个盒子里(class),出入口都在这个盒子上。你要用就将这个盒子拿来用,链接出入口,就能用了,不用就能够直接扔,对你代码没什么影响。

对程序员来讲,使用封装的目的:

  1. 偷懒,辛苦一次,后面都能少敲不少代码,加强了代码得复用性
  2. 简化代码,看起来更容易懂
  3. 隐藏核心实现逻辑代码,简化外部逻辑,而且不让其余人修改,jar 都这么干
  4. 一对一,一个功能就只为这个功能服务;避免头发绳子一块用,致使最后一团糟

三、封装的实现步骤

img

    须要注意:对封装的属性不必定要经过get/set方法,其余方法也能够对封装的属性进行操做。固然最好使用get/set方法,比较标准。


A、访问修饰符

img

    从表格能够看出从上到下封装性愈来愈差

B、this关键字

 1.this关键字表明当前对象

  this.属性 操做当前对象的属性

  this.方法 调用当前对象的方法。

 2.封装对象的属性的时候,常常会使用this关键字。

 3.当getter和setter函数参数名和成员函数名重合的时候,可使用this****区别。如:

img

C、Java 中的内部类

 内部类( Inner Class )就是定义在另一个类里面的类。与之对应,包含内部类的类被称为外部类。

 那么问题来了:那为何要将一个类定义在另外一个类里面呢?清清爽爽的独立的一个类多好啊!!

 答:内部类的主要做用以下:

  1. 内部类提供了更好的封装,能够把内部类隐藏在外部类以内,不容许同一个包中的其余类访问该类。
  2. 内部类的方法能够直接访问外部类的全部数据,包括私有的数据
  3. 内部类所实现的功能使用外部类一样能够实现,只是有时使用内部类更方便。

  内部类可分为如下几种:

  • 成员内部类
  • 静态内部类
  • 方法内部类
  • 匿名内部类  

3、多态

一、多态的概念

面向对象的多态性,即“一个接口,多个方法”。多态性体如今父类中定义的属性和方法被子类继承后,能够具备不一样的属性或表现方式。多态性容许一个接口被多个同类使用,弥补了单继承的不足。多态概念能够用树形关系来表示,如图 4 所示。

图4 多态示例图

从图 4 中能够看出,老师类中的许多属性和方法能够被语文老师类和数学老师类同时使用,这样也不易出错。

二、多态的好处

可替换性(substitutability)。多态对已存在代码具备可替换性。例如,多态对圆Circle类工做,对其余任何圆形几何体,如圆环,也一样工做。

可扩充性(extensibility)。多态对代码具备可扩充性。增长新的子类不影响已存在类的多态性、继承性,以及其余特性的运行和操做。实际上新加子类更容易得到多态功能。例如,在实现了圆锥、半圆锥以及半球体的多态基础上,很容易增添球体类的多态性。

接口性(interface-ability)。多态是超类经过方法签名,向子类提供了一个共同接口,由子类来完善或者覆盖它而实现的。

灵活性(flexibility)。它在应用中体现了灵活多样的操做,提升了使用效率。

简化性(simplicity)。多态简化对应用软件的代码编写和修改过程,尤为在处理大量对象的运算和操做时,这个特色尤其突出和重要。

子代父类实例化,而后就至关于一个父亲有不少儿子,送快递的给这个父亲的儿子送东西,他只须要送到父亲的家就好了,至于具体是那个儿子的,父亲还会分不清本身的儿子么,因此你就不用操心了。

使用多态是一种好习惯 多态方式声明是一种好的习惯。当咱们建立的类,使用时,只用到它的超类或接口定义的方法时,咱们能够将其索引声明为它的超类或接口类型。

它的好处是,若是某天咱们对这个接口方法的实现方式变了,对这个接口又有一个新的实现类,咱们的程序也须要使用最新的实现方式,此时只要将对象实现修改一下,索引无需变化。

好比Map< String,String> map = new HashMap < String,String>();

想换成HashTable实现,能够Map< String,String> map = new HashTable < String,String>();

好比写一个方法,参数要求传递List类型,你就能够用List list = new ArrayList()中的list传递,可是你写成ArrayList list = new ArrayList()是传递不进去的。尽管方法处理时都同样。另外,方法还能够根据你传递的不一样list(ArrayList或者LinkList)进行不一样处理。

三、Java中的多态

java里的多态主要表如今两个方面:

A、引用多态  

  父类的引用能够指向本类的对象;

  父类的引用能够指向子类的对象;

  这两句话是什么意思呢,让咱们用代码来体验一下,首先咱们建立一个父类Animal和一个子类Dog,在主函数里以下所示:

img

  注意:咱们不能使用一个子类的引用来指向父类的对象,如:img

  这里咱们必须深入理解引用多态的意义,才能更好记忆这种多态的特性。为何子类的引用不能用来指向父类的对象呢?我在这里通俗给你们讲解一下:就以上面的例子来讲,咱们能说“狗是一种动物”,可是不能说“动物是一种狗”,狗和动物是父类和子类的继承关系,它们的从属是不能颠倒的。当父类的引用指向子类的对象时,该对象将只是当作一种特殊的父类(里面有重写的方法和属性),反之,一个子类的引用来指向父类的对象是不可行的!!

B、方法多态

  根据上述建立的两个对象:本类对象和子类对象,一样都是父类的引用,当咱们指向不一样的对象时,它们调用的方法也是多态的。

  建立本类对象时,调用的方法为本类方法;

  建立子类对象时,调用的方法为子类重写的方法或者继承的方法;

  使用多态的时候要注意:若是咱们在子类中编写一个独有的方法(没有继承父类的方法),此时就不能经过父类的引用建立的子类对象来调用该方法!!!

  注意: 继承是多态的基础。


C、引用类型转换

 了解了多态的含义后,咱们在平常使用多态的特性时常常须要进行引用类型转换。

 引用类型转换:

 1.向上类型转换(隐式/自动类型转换),是小类型转换到大类型

  就以上述的父类Animal和一个子类Dog来讲明,当父类的引用能够指向子类的对象时,就是向上类型转换。如:

img

  2. 向下类型转换(强制类型转换),是大类型转换到小类型(有风险,可能出现数据溢出)。

  将上述代码再加上一行,咱们再次将父类转换为子类引用,那么会出现错误,编译器不容许咱们直接这么作**,虽然咱们知道这个父类引用指向的就是子类对象,可是编译器认为这种转换是存在风险的。**如:

img

  那么咱们该怎么解决这个问题呢,咱们能够在animal前加上(Dog)来强制类型转换。如:img

  可是若是父类引用没有指向该子类的对象,则不能向下类型转换,虽然编译器不会报错,可是运行的时候程序会出错,如:img

  其实这就是上面所说的子类的引用指向父类的对象,而强制转换类型也不能转换!!

  还有一种状况是父类的引用指向其余子类的对象,则不能经过强制转为该子类的对象。如:

    img

  这是由于咱们在编译的时候进行了强制类型转换,编译时的类型是咱们强制转换的类型,因此编译器不会报错,而当咱们运行的时候,程序给animal开辟的是Dog类型的内存空间,这与Cat类型内存空间不匹配,因此没法正常转换。这两种状况出错的本质是同样的,因此咱们在使用强制类型转换的时候要特别注意这两种错误!!下面有个更安全的方式来实现向下类型转换。。。。

  3. instanceof运算符,来解决引用对象的类型,避免类型转换的安全性问题。

  instanceof是Java的一个二元操做符,和==,>,<是同一类东东。因为它是由字母组成的,因此也是Java的保留关键字。它的做用是测试它左边的对象是不是它右边的类的实例,返回boolean类型的数据。

  咱们来使用instanceof运算符来规避上面的错误,代码修改以下:

  img

  利用if语句和instanceof运算符来判断两个对象的类型是否一致。

  **补充说明:**在比较一个对象是否和另外一个对象属于同一个类实例的时候,咱们一般能够采用instanceof和getClass两种方法经过二者是否相等来判断,可是二者在判断上面是有差异的。Instanceof进行类型检查规则是:你属于该类吗?或者你属于该类的派生类吗?而经过getClass得到类型信息采用==来进行检查是否相等的操做是严格的判断,不会存在继承方面的考虑

  **总结:**在写程序的时候,若是要进行类型转换,咱们最好使用instanceof运算符来判断它左边的对象是不是它右边的类的实例,再进行强制转换。


D、重写和重载 

多态通常能够分为两种,一个是重写override,一个是重载overload。

重写是因为继承关系中的子类有一个和父类同名同参数的方法,会覆盖掉父类的方法。重载是由于一个同名方法能够传入多个参数组合。

注意,同名方法若是参数相同,即便返回值不一样也是不能同时存在的,编译会出错。

从jvm实现的角度来看,重写又叫运行时多态,编译时看不出子类调用的是哪一个方法,可是运行时操做数栈会先根据子类的引用去子类的类信息中查找方法,找不到的话再到父类的类信息中查找方法。

而重载则是编译时多态,由于编译期就能够肯定传入的参数组合,决定调用的具体方法是哪个了。

1. 向上转型和向下转型

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;
}

总结: 向上转型和向下转型都是针对引用的转型,是编译期进行的转型,根据引用类型来判断使用哪一个方法。而且在传入方法时会自动进行转型(有须要的话)。运行期将引用指向实例,若是是不安全的转型则会报错,若安全则继续执行方法。

2. 编译期的静态分派

其实就是根据引用类型来调用对应方法。

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();
}

3. 方法重载优先级匹配

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");
//    }

参考文章

http://www.javashuo.com/article/p-ohvhntlc-ke.html

http://www.javashuo.com/article/p-tfbleich-bp.html

http://c.biancheng.net/view/939.html

https://www.runoob.com/

https://blog.csdn.net/android_hl/article/details/53228348

微信公众号

Java技术江湖

若是你们想要实时关注我更新的文章以及分享的干货的话,能够关注个人公众号【Java技术江湖】一位阿里 Java 工程师的技术小站,做者黄小斜,专一 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!

Java工程师必备学习资源: 一些Java工程师经常使用学习资源,关注公众号后,后台回复关键字 “Java” 便可免费无套路获取。

个人公众号

我的公众号:黄小斜

做者是 985 硕士,蚂蚁金服 JAVA 工程师,专一于 JAVA 后端技术栈:SpringBoot、MySQL、分布式、中间件、微服务,同时也懂点投资理财,偶尔讲点算法和计算机理论基础,坚持学习和写做,相信终身学习的力量!

程序员3T技术学习资源: 一些程序员学习技术的资源大礼包,关注公众号后,后台回复关键字 “资料” 便可免费无套路获取。

相关文章
相关标签/搜索