程序技术好文:重载与重写的区别

简介: 程序技术好文:重载与重写的区别

方法重载是指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同


方法重写是存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型


注:


(1)子类中不能重写父类中的final方法


(2)子类中必须重写父类中的abstract方法


首先我们来讲讲:重载(Overloading)


(1) 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。


重载Overloading是一个类中多态性的一种表现。


(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。


调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。


(3) 重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。


下面是重载的例子:


package c04.answer;//这是包名


//这是这个程序的第一种编程方法,在main方法中先创建一个Dog类实例,然后在Dog类的构造方法中利用this关键字调用不同的bark方法。


不同的重载方法bark是根据其参数类型的不同而区分的。


//注意:除构造器以外,编译器禁止在其他任何地方中调用构造器。


package c04.answer;


public class Dog {


Dog()


{


this.bark();


}


void bark()//bark()方法是重载方法


{


System.out.println(\"no barking!\");


this.bark(\"female\", 3.4);


}


void bark(String m,double l)//注意:重载的方法的返回值都是一样的,


{


System.out.println(\"a barking dog!\");


this.bark(5, \"China\");


}


void bark(int a,String n)//不能以返回值区分重载方法,而只能以“参数类型”和“类名”来区分


{


System.out.println(\"a howling dog\");


}


public static void main(String【】 args)


{


Dog dog = new Dog();


//dog.bark(); 【Page】


//dog.bark(\"male\", \"yellow\");


//dog.bark(5, \"China\");


  然后我们再来谈谈 重写(Overriding)


(1) 父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。


但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。


方法重写又称方法覆盖。


(2)若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。


如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。


(3)子类函数的访问修饰权限不能少于父类的;


下面是重写的例子:


概念:即调用对象方法的机制。


动态绑定的内幕:


1、编译器检查对象声明的类型和方法名,从而获取所有候选方法。试着把上例Base类的test注释掉,这时再编译就无法通过。


2、重载决策:编译器检查方法调用的参数类型,从上述候选方法选出唯一的那一个(其间会有隐含类型转化)。


如果编译器找到多于一个或者没找到,此时编译器就会报错。试着把上例Base类的test(byte b)注释掉,这时运行结果是1 1。


3、若方法类型为priavte static final ,java采用静态编译,编译器会准确知道该调用哪


个方法。


4、当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用对象的实际类型相匹配的方法版本。


在例子中,b所指向的实际类型是TestOverriding,所以b.test(0)调用子类的test。


但是,子类并没有重写test(byte b),所以b.test((byte)0)调用的是父类的test(byte b)。


如果把父类的(byte b)注释掉,则通过第二步隐含类型转化为int,最终调用的是子类的test(int i)。


学习总结:


多态性是面向对象编程的一种特性,和方法无关,


简单说,就是同样的一个方法能够根据输入数据的不同,做出不同的处理,即方法的


重载——有不同的参数列表(静态多态性)


  而当子类继承自父类的相同方法,输入数据一样,但要做出有别于父类的响应时,你就要覆盖父类方法,


即在子类中重写该方法——相同参数,不同实现(动态多态性)


OOP三大特性:继承,多态,封装。


public class Base


{


void test(int i)


{


System.out.print(i);


}


void test(byte b)


{


System.out.print(b);


}


}


public class TestOverriding extends Base


{


void test(int i)


{


i++;


System.out.println(i);


}


public static void main(String【】agrs)


{


Base b=new TestOverriding();


b.test(0)


b.test((byte)0)


}


}


这时的输出结果是1 0,这是运行时动态绑定的结果。


重写的主要优点是能够定义某个子类特有的特征:


public class Father{


public void speak(){


System.out.println(Father);


}


}


public class Son extends Father{


public void speak(){


System.out.println("son");


}


}


这也叫做多态性,重写方法只能存在于具有继承关系中,重写方法只能重写父类非私有的方法。


当上例中Father类speak()方法被private时,Son类不能重写出Father类speak()方法,此时Son类speak()方法相当与在Son类中定义的一个speak()方法。


Father类speak()方法一但被final时,无论该方法被public,protected及默认所修饰时,Son类根本不能重写Father类speak()方法,


试图编译代码时,编译器会报错。例:


public class Father{


final public void speak(){


System.out.println("Father");


}


}


public class Son extends Father{


public void speak(){


System.out.println("son");


}


} //编译器会报错;


Father类speak()方法被默认修饰时,只能在同一包中,被其子类被重写,如果不在同一包则不能重写。


Father类speak()方法被protoeted时,不仅在同一包中,被其子类被重写,还可以不同包的子类重写。


重写方法的规则:


1、参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。


2、返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。


3、访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)


4、重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。例如:


父类的一个方法申明了一个检查异常IOException,在重写这个方法是就不能抛出Exception,只能抛出IOException的子类异常,可以抛出非检查异常。


而重载的规则:


1、必须具有不同的参数列表;


2、可以有不责骂的返回类型,只要参数列表不同就可以了;


3、可以有不同的访问修饰符;


4、可以抛出不同的异常;


重写与重载的区别在于:


重写多态性起作用,对调用被重载过的方法可以大大减少代码的输入量,同一个方法名只要往里面传递不同的参数就可以拥有不同的功能或返回值。


用好重写和重载可以设计一个结构清晰而简洁的类,可以说重写和重载在编写代码过程中的作用非同一般.


面试题:重载(Overload)和重写(Override)的区别。重载的方法能否根据返回类型进行区分?


答:方法的重载和重写都是实现多态的方式,区别在于前者实现的是编译时的多态性,而后者实现的是运行时的多态性。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载;重写发生在子类与父类之间,重写要求子类被重写方法与父类被重写方法有相同的参数列表,有兼容的返回类型,比父类被重写方法更好访问,不能比父类被重写方法声明更多的异常(里氏代换原则)。重载对返回类型没有特殊的要求,不能根据返回类型进行区分。


Overload(重载)


(1) 重载Overload是一个类中多态性的一种表现。是编译时的多态性。方法重载是让类以统一的方式处理不同类型数据的一种手段。重载发生在一个类中,同名的方法如果有不同的参数列表(参数类型不同、参数个数不同或者二者都不同)则视为重载。


(2) Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数列表。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性。


(3) 重载的时候,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。


(4) 不能通过访问权限、返回类型、抛出的异常进行重载;


(5) 方法的异常类型和数目不会对重载造成影响;


Override(重写、覆盖)


(1) 父类与子类之间的多态性,对父类的函数进行重新定义。是运行时的多样性。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Override)。在Java中,子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。


(2)若子类中的方法与父类中的某一方法具有相同的方法名、参数列表和兼容的返回类型,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。


(3)子类函数的访问修饰权限不能少于父类的。


普通的方法继承:


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


}


public class OverrideTest {


public static void main(String 【】args){


Parent p = new Parent();


Child c = new Child();


p.make(1); //Parent int: 1


p.make(new Integer(1)); //Parent int: 1


c.make(1); //Parent int: 1


c.make(new Integer(1)); //Parent int: 1


}


}


普通的重载,参数列表相同,返回值相同


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


@Override


public Parent make(int i) {


System.out.println("Child int: "+i);


return null;


}


}


public class OverrideTest {


public static void main(String 【】args){


Parent p = new Parent();


Child c = new Child();


p.make(1); //Parent int: 1


//代码效果参考:http://hnjlyzjd.com/hw/wz_24103.html

p.make(new Integer(1)); //Parent int: 1

c.make(1); //Child int: 1


c.make(new Integer(1)); //Child int: 1


}


}


重载,但是子类的返回类型是父类被重写方法的子类,即重写返回方法兼容,编译通过。


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


@Override


public Child make(int i) {


System.out.println("Child int: "+i);


return null;


}


}


public class OverrideTest {


public static void main(String 【】args){


Parent p = new Parent();


Child c = new Child();


p.make(1); //Parent int: 1


p.make(new Integer(1)); //Parent int: 1


c.make(1); //Child int: 1


c.make(new Integer(1)); //Child int: 1


}


}


突然想到一道int和Integer的面试题,Integer的自动拆箱与装箱,不知道如果把Child的方法参数由int改成Integer会如何,发现编译出错,可见参数列表需要完全相同。


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


@Override


public Child make(Integer i) { //编译出错


System.out.println("Child Integer: "+i);


return null;


}


}


不重写make(int)方法,另写一个make(Integer)方法(此处应该算重载了,继承了父类的make(int)方法,而make(Integer)参数列表不同):


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


public Child make(Integer i) {


System.out.println("Child Integer: "+i);


return null;


}


}


public class OverrideTest {


public static void main(String 【】args){


Parent p = new Parent();


Child c = new Child();


p.make(1); //Parent int: 1


p.make(new Integer(1)); //Parent int: 1


c.make(1); //Parent int: 1


c.make(new Integer(1)); //Child Integer: 1


}


}


此时c.make(new Integer(1))则调用Child.make(Integer)方法,不会拆包并调用父类Father.make(int)方法。


重写make(int)方法,并编写make(Integer)方法:


class Parent {


public Parent make(int i) {


System.out.println("Parent int: "+i);


return null;


}


}


class Child extends Parent{


@Override


public Parent make(int i) {


System.out.println("Child int: "+i);


return null;


}


public Child make(Integer i) {


System.out.println("Child Integer: "+i);


return null;


}


}


public class OverrideTest {


public static void main(String 【】args){


Parent p = new Parent();


Child c = new Child();


p.make(1); //P

相关文章
|
算法 计算机视觉 索引
OpenCV(四十六):特征点匹配
OpenCV(四十六):特征点匹配
747 0
|
JavaScript 数据格式
js 计算两个时间的时间差
如题,就像题目说的需要计算出时间差,虽然不太难,但这个需求经常会在项目中遇到的,我在这边做一下整理,希望能够尽量全的整理出来。有需要的朋友可以做一下参考,喜欢的可以点波赞,或者关注一下,希望可以帮到大家。 本文首发于我的个人blog:obkoro1.com 计算时间差原理: getTime()方法 方法定义: getTime() 方法可返回距 1970 年 1 月 1 日之间的毫秒数。 通常我们计算时间差都是通过获取两个时间数据,然后分别使用getTime()方法返回与固定的1970 年 1 月 1 日的时间差,通过对返回毫秒数的差,换算成时间单位,得出两个时间的时间差。 开始操作:
1387 0
js 计算两个时间的时间差
|
8月前
|
存储 算法 调度
基于和声搜索优化算法的机器工作调度matlab仿真,输出甘特图
本程序基于和声搜索优化算法(Harmony Search, HS),实现机器工作调度的MATLAB仿真,输出甘特图展示调度结果。算法通过模拟音乐家即兴演奏寻找最佳和声的过程,优化任务在不同机器上的执行顺序,以最小化完成时间和最大化资源利用率为目标。程序适用于MATLAB 2022A版本,运行后无水印。核心参数包括和声记忆大小(HMS)等,适应度函数用于建模优化目标。附带完整代码与运行结果展示。
245 24
|
机器学习/深度学习 边缘计算 自然语言处理
《C++赋能文本分类与情感分析:开启智能文本处理之旅》
在数字化信息爆炸的时代,文本数据激增,文本分类和情感分析成为关键任务。C++以其高效性能,为实现这些任务提供了有力支持。本文介绍了文本分类和情感分析的基础概念、特征提取方法(词袋模型、TF-IDF、词向量)、模型选择与构建(朴素贝叶斯、SVM、CNN、RNN)、模型训练与优化,以及应用场景和未来展望。C++在这些领域展现出巨大潜力,助力数字化转型和智能化发展。
187 11
|
前端开发 UED
next/dynamic的动态导入
next/dynamic的动态导入
|
机器学习/深度学习 人工智能 数据可视化
小滑块上个斜面,难倒多少高中生?现在,AI让它动起来了
《Augmented Physics:基于机器学习的物理学习工具》 高中物理学习中,小滑块上斜面等问题常让学生困惑。Augmented Physics利用AI技术,将静态物理图示转化为交互式模拟,通过增强实验、动画图示、双向操作和参数可视化等技术,帮助学生直观理解物理概念。研究表明,该工具能有效提升学生对物理概念的理解,具备广阔的应用前景。
292 1
|
机器学习/深度学习 自然语言处理 搜索推荐
智能语音交互:技术原理与应用前景####
【10月更文挑战第25天】 一句话概括本文主旨,并引发读者兴趣。 智能语音交互技术,作为人工智能领域的重要分支,正以前所未有的速度融入我们的生活,从简单的语音助手到复杂的多轮对话系统,它不仅重塑了人机交互的方式,还为多个行业带来了革命性的变化。本文将深入浅出地探讨智能语音交互的技术原理、当前主流技术路线、面临的挑战及未来发展趋势,为读者揭开这一高科技领域的神秘面纱。 ####
|
开发工具 git
GitHub——Error: Process completed with exit code 126.
GitHub——Error: Process completed with exit code 126.
341 1
GitHub——Error: Process completed with exit code 126.
|
JavaScript 前端开发 Go
Github 2024-08-12 开源项目周报 Top14
本周Github Trendings共有14个项目上榜,按开发语言汇总如下:Python项目7个,TypeScript项目5个,C项目2个,JavaScript项目2个,Go和Batchfile项目各1个。其中亮点包括开发者职业成长指南、Windows激活工具、ComfyUI图形界面、AFFiNE知识库、易采集可视化爬虫等项目,涵盖多种实用工具和开源平台。
733 1
|
存储 缓存 索引
数据结构——顺序表的概念和基本操作(超全超详细)
数据结构——顺序表的概念和基本操作(超全超详细)