公众号偶然看到的一个帖子,构造方法,类方法,final方法,哪些能覆盖,哪些能重载,初学时也是被这些术语搞的很迷糊

现在有时间了对这些做一个总结。全是自己的语言,可能不是很全面,表达意思应该够清楚

一、叫法

构造方法:又叫构造器,构造函数。通常有无参构造器和带参数的构造器2种,每个类都有一个构造方法(如果没有显式的给出来,

那么也有一个默认的无参构造器)无返回类型修饰符。访问修饰符可以是public,也可以是private,比如常见的单例模式就要求构

造函数私有化。

类方法:static修饰符修饰的方法。因为static修饰的方法是属于类的而不是属于实例的(这个描述各种书籍上非常常见),因此不必

去new 一个实例来调用,而是直接类名.方法名来调用这种方法,因此也称为类方法。

final方法:最终的、不可改变的、终极的方法。怎么叫都行,单词修饰很清楚了,用了final表明设计上不再会去修改他,很巧,一

个叫abstract的修饰符就是要设计者去实现去重写的,因此可以知道final和abstract永远不能共存。

覆盖:又叫重写,Override。多态是java的特性,覆盖是表现多态特性的具体做法。《Effective Java》有一个章节特别提出了,如

果是覆盖方法,请一定记得加上@Override,在接下来的代码描述中你会看到,很多种方法混杂在一起的时候看起来是多么的难受

重载:重载只发生在一个类中,记住这点很重要,这也是跟覆盖这个概念撇清关系的最重要一点。重载要求同一个类中方法名相同

而参数列表不同。参数列表,就是入参的个数,类型,顺序。抓住定义中的这两点,其他的通过什么返回值,访问权限,异常来重

载一个方法那就是扯淡,混淆,不行。

二、行还是不行?

首先看下重载。最经典最常见的莫过于这两个例子:构造方法的重载和System.out.println()这个方法了。我们直接看代码:

public abstract class ClassTest {

    private int a;

    /**
* abstract 和 final不能共存,报错
*/
abstract final void test(); /**
* 构造方法
*/
public ClassTest() {
System.out.println("调用父类无参构造方法");
} /**
* 构造方法重载为带参的构造器
*/
public ClassTest(int a) {
this.a = a;
System.out.println("调用重载的带参构造方法");
System.out.println(this.a);
} /**
* 类方法(静态方法)
*/
public static void staticMethod() {
System.out.println("调用父类static方法(类方法)");
} /**
* 类方法可以被重载
*/
public static void staticMethod(String s) {
System.out.println("调用重载的类方法,s=" + s);
} /**
* final方法
*/
public final void finalMethod() {
System.out.println("调用父类final方法");
} /**
* final方法可以被重载
*/
public final void finalMethod(String s) {
System.out.println("调用重载的final方法,s=" + s);
} }

写一个客户端调用一下:

public class Client {
public static void main(String[] args) {
ClassTest.staticMethod();
ClassTest.staticMethod("hello");
}
}

我们得出如下结论:构造方法,类方法,final方法均可以被重载

接着我们看下覆盖的情况:

还是用之前的定义的类,不过我们加入了一些别的情况:父类private的final方法和private的方法

public class ClassTest {

    /**
* 构造方法
*/
public ClassTest() {
System.out.println("调用父类无参构造方法");
} /**
* 类方法(静态方法)
*/
public static void staticMethod() {
System.out.println("调用父类static方法(类方法)");
} /**
* final方法
*/
private final void finalMethod0() {
System.out.println("调用父类private final方法");
} /**
* final方法
*/
public final void finalMethod() {
System.out.println("调用父类public final方法");
} /**
* 普通的私有方法
*/
private void privateMethod() {
    System.out.println("调用父类public final方法");
}
}

子类是:

public class SubClassTest extends ClassTest {

    /**
* 报错提示:父类构造器不可覆盖
*/
@Override
public ClassTest() {
System.out.println("覆盖父类构造方法");
} /**
* 报错提示:父类的静态方法不能覆盖
*/
@Override
public static void staticMethod() {
System.out.println("覆盖父类静态方法");
} /**
* 上面的@Override去掉,不再报错
* 说明这个方法只是和父类的静态方法同名了而已,他是子类独有的,与父类的没半毛钱关系
* 如果决定覆盖,请敲上@Override,一般做项目也不会像我这样测这些奇怪的情况,所以不加也知道是覆盖了,但是还是请加上
*/
public static void staticMethod() {
System.out.println("子类的同名方法");
} /**
* 报错提示:final方法不能被覆盖
*/
// @Override
// public final void finalMethod() {
// System.out.println("覆盖final方法");
// } /**
* 未加@Override
* 错误提示:final方法不能覆盖
* 说明子类的final方法连名字都不能跟父类的同名,否则认为是覆盖
*/
public final void finalMethod() {
System.out.println("覆盖final方法");
} /**
* 未加@Override
* 父类中该方法是private final的
* 子类可以拥有对应的public权限的final同名方法
*/
public final void finalMethod0() {
System.out.println("调用子类同名的final方法");
} /**
* 错误提示:父类私有方法不能被覆盖
*/
@Override
public void privateMethod() {
System.out.println("调用普通的private方法");
} }

编译结果我在注释里都写了,我们可以得出:构造方法,类方法,final方法都不能覆盖

注意:

  1、子类可以拥有和父类同名的static方法,参看上面的staticMethod方法的注释,这个方法和父类的那个没半毛钱关系

  2、父类的public final方法,子类不能覆盖,也不能有自己的同样的方法(这就是我为啥,effective java也,强调加上@Override的原因)

  3、父类的private final方法,子类可以有对应的public final的,但是也和父类对应的这个方法没半毛钱关系,只是语法上允许

注意:以上的类直接复制在开发工具上会报错的,这也是我们想要的

三、为什么不行?从意义和设计上窥探下

  static方法为什么不能被覆盖,我们试着从意义上理解下,static是类的不是实例的,意味着它是无状态的,而覆盖发生在多态中,也就是

每个实例各自去show,从java运行角度讲,static的方法在编译时就绑定完了,而多态要在运行时才确定,该调用谁覆盖后的方法。

  final方法为什么不能覆盖,设计final关键字的意义是,开发者知道这个方法一旦完成,就不打算再修改它,子类如果需要,可以直接调用

如果各个子类也去覆盖这个final方法,那父类的这个方法再用final修饰就没啥意义了

  最后private修饰的方法会被隐形的指定为final的,所以也不能覆盖,这个可以在Thinking in Java中找到

以上是个人一些小总结,不到之处,还请指正~~

Java - 关于覆盖和重写的总结的更多相关文章

  1. java的覆盖重写隐藏和C#中的不同

    先看下C#中的: C#中覆盖 隐藏 重写这三种有不同的意义,而Java中不同. 1. java中没有new ,使用new会报错,编译不通过. 2. java中重写和覆盖应该是一个意思 static c ...

  2. Java中方法的重写与成员变量的隐藏

    这篇文章讨论了Java面向对象概念中一个基本的概念–Field Hiding(隐藏成员变量) 在讨论这个问题之前,我们看一段特别特别简单的代码,请问一下方法的数据结果是什么? public class ...

  3. Java继承之方法重写

    目录 Java继承之方法重写 代码体现 概念 注意事项 "两同两小一大" 其他注意点 重写与重载 @Override注解 Java继承之方法重写 在Java继承中,子类可以获得父类 ...

  4. Java:重载和重写

    Java:重载和重写 对 Java 中的 重载和重写 这个概念,做一个微不足道的小小小小结 重载 重载:编译时多态,同一个类中的同名的方法,参数列表不同,与返回值无关. 有以下几点: 方法名必须相同: ...

  5. c++中的隐藏、重载、覆盖(重写)

    转自c++中的隐藏.重载.覆盖(重写) 1 重载与覆盖 成员函数被重载的特征: (1)相同的范围(在同一个类中): (2)函数名字相同: (3)参数不同: (4)virtual关键字可有可无. 覆盖是 ...

  6. 【C++】三大概念要分清--重载,隐藏(重定义,覆盖(重写)

    { c++三大概念要分清--重载,隐藏(重定义),覆盖(重写)} 重载 •  概念:在同一个作用域内:函数名相同,参数列表不同(参数个数不同,或者参数类型不同,或者参数个数和参数类型都不同),返回值类 ...

  7. java多态性方法的重写Overriding和重载Overloading详解

    java多态性方法的重写Overriding和重载Overloading详解 方法的重写Overriding和重载Overloading是Java多态性的不同表现.重写Overriding是父类与子类 ...

  8. c++三大概念要分清--重载,隐藏(重定义),覆盖(重写)

    重载,隐藏(重定义),覆盖(重写)—这几个名词看着好像很像,不过其实一样都不一样!! 综述: 说明:覆盖中的访问修饰符可以不同是指可以不用显示地用virtual:当访问修饰符改为const或者stat ...

  9. C# 笔记——覆盖和重写

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Cons ...

随机推荐

  1. 数据库MySQL--常见基础命令

    基础命令: 查看所有数据库:show databases; 打开指定的数据库:use 库名: 查看当前库的所有表:show tables; 查看数据库其他库中的表:show tables from 库 ...

  2. vue v-model :

    v-model : 通过v-model 进行双向绑定 ,将data的数据与input 绑定在一起,呈现在页面上 <!DOCTYPE html> <html lang="en ...

  3. [JZOJ6347] 【NOIP2019模拟2019.9.8】ZYB玩字符串

    题目 题目大意 有一个字符串\(p\).一开始字符串\(s\)为空串. 接下来进行若干次操作:在\(s\)的某个空隙中插入\(p\). 给出操作后的\(s\),问长度最小的\(p\). 思考历程 感觉 ...

  4. 【luoguP4721】分治 FFT

    description 给定长度为\(n-1\)的数组\(g[1],g[2],..,g[n-1]\),求\(f[0],f[1],..,f[n-1]\),其中 \[f[i]=\sum_{j=1}^if[ ...

  5. 关于CTreeView中CTreeCtrl空间的使用

    昨天QQ群里有人问我怎么实现CTreeCtrl的功能,说实话,我也是一个VC 的初级学者,没有弄过CTreeView的代码,参考了MSDN后,写了一小段代码,和大家一起分享,其中包括窗口切分,都是比较 ...

  6. text-html 转译

    var HtmlUtil = { 2 /*1.用浏览器内部转换器实现html编码(转义)*/ 3 htmlEncode:function (html){ 4 //1.首先动态创建一个容器标签元素,如D ...

  7. Java笔记 – JDBC编程

    JDBC通过分层技术实现了跨数据库编程.为不同的数据库开发了统一的编程接口,为不同的数据库提供了不同的JAR类库. 一.JDBC基础 1.开发环境 (1)下载对应的Jar包 Oracle的本地Jar包 ...

  8. reboot与shutdown -r now 区别与联系(又收集了init和halt的小知识)

    在linux命令中reboot是重新启动,shutdown -r now是立即停止然后重新启动,都说他们两个是一样的,其实是有一定的区别的. shutdown命令可以安全地关闭或重启Linux系统,它 ...

  9. 逆元 组合A(n,m) C(n,m)递推 隔板法

    求逆元 https://blog.csdn.net/baidu_35643793/article/details/75268911 int inv[N]; void init(){ inv[] = ; ...

  10. mysql简单的操作

    启动数据库服务     net start mysql     停止数据库服务     net stop mysql      退出数据库      exit     保存操作及结果 将在命令行窗口中 ...