建议33: 不要覆写静态方法

我们知道在Java中可以通过覆写(Override)来增强或减弱父类的方法和行为,但覆写是针对非静态方法(也叫做实例方法,只有生成实例才能调用的方法)的,不能针对静态方法(static修饰的方法,也叫做类方法),为什么呢?我们先看一个例子,代码如下:

 public class Client {
public static void main(String[] args) {
Base base = new Sub();
//调用非静态方法
base.doAnything();
//调用静态方法
base.doSomething();
}
} class Base{
//父类静态方法
public static void doSomething(){
System.out.println("我是父类静态方法");
} //父类非静态方法
public void doAnything(){
System.out.println("我是父类非静态方法");
}
} class Sub extends Base{
//子类同名、同参数的静态方法
public static void doSomething(){
System.out.println("我是子类静态方法");
}
//覆写父类的非静态方法
@Override
public void doAnything(){
System.out.println("我是子类非静态方法");
}
}

运行输出:

我是子类非静态方法
我是父类静态方法

这个结果很让人困惑,同样是调用子类方法,一个执行了子类方法,一个执行了父类方法,两者的差别仅仅是有无static修饰,却得到不同的输出结果,原因何在呢?

我们知道一个实例对象有两个类型:表面类型(Apparent Type)和实际类型(Actual Type),表面类型是声明时的类型,实际类型是对象产生时的类型,比如我们例子,变量base的表面类型是Base,实际类型是Sub。对于非静态方法,它是根据对象的实际类型来执行的,也就是执行了Sub类中的doAnything方法。而对于静态方法来说就比较特殊了,首先静态方法不依赖实例对象,它是通过类名访问的;其次,可以通过对象访问静态方法,如果是通过对象调用静态方法,JVM则会通过对象的表面类型查找到静态方法的入口,继而执行之。因此上面的程序打印出“我是父类静态方法”,也就不足为奇了。

在子类中构建与父类相同的方法名、输入参数、输出参数、访问权限(权限可以扩大),并且父类、子类都是静态方法,此种行为叫做隐藏(Hide),它与覆写有两点不同:

表现形式不同。隐藏用于静态方法,覆写用于非静态方法。在代码上的表现是:@Override注解可以用于覆写,不能用于隐藏。

职责不同。隐藏的目的是为了抛弃父类静态方法,重现子类方法,例如我们的例子,Sub.doSomething的出现是为了遮盖父类的Base.doSomething方法,也就是期望父类的静态方法不要破坏子类的业务行为;而覆写则是将父类的行为增强或减弱,延续父类的职责。

解释了这么多,我们回头看一下本建议的标题:静态方法不能覆写,可以再续上一句话,虽然不能覆写,但是可以隐藏。顺便说一下,通过实例对象访问静态方法或静态属性不是好习惯,它给代码带来了“坏味道”,建议读者阅之戒之。

[改善Java代码]不要覆写静态方法的更多相关文章

  1. [改善Java代码]推荐覆写toString方法

    建议49: 推荐覆写toString方法 为什么要覆写toString方法,这个问题很简单,因为Java提供的默认toString方法不友好,打印出来看不懂,不覆写不行,看这样一段代码: public ...

  2. [改善Java代码]覆写equals方法必须覆写hashCode方法

    覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先 ...

  3. [改善Java代码]覆写equals方法时不要识别不出自己

    建议45: 覆写equals方法时不要识别不出自己 我们在写一个JavaBean时,经常会覆写equals方法,其目的是根据业务规则判断两个对象是否相等,比如我们写一个Person类,然后根据姓名判断 ...

  4. [改善Java代码]覆写变长方法也循规蹈矩

    建议6:覆写变长方法也循规蹈矩 在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看 ...

  5. [改善Java代码]不推荐覆写start方法

    多线程比较简单的方式是继承Thread类,然后覆写run()方法,在客户端程序中通过调用对象的start方法即可启动一个线程,这个是多线程程序的标准写法. 错误代码: public class Cli ...

  6. JAVA继承与覆写

    实例:数组操作 首先是开发一个整型数组父类,要求从外部控制数组长度,并实现保存数据以及输出.然后子类中实现排序和反转. 基础父类代码如下: class Array { private int data ...

  7. [改善Java代码]asList方法产生的List对象不可更改

    上一个建议之处了asList方法在转换基本类型数组时候存在的问题,在看下asList方法返回的列表有何特殊的地方.看代码: import java.util.Arrays; import java.u ...

  8. [改善Java代码]警惕泛型是不能协变和逆变的

    什么叫做协变(covariance)和逆变(contravariance)? 在变成语言的类型框架中,协变和逆变是指宽类型和窄类型在某种情况下(如参数,泛型,返回值)替换或交换的特性,简单的说,协变是 ...

  9. [改善Java代码]不要在构造函数中抛出异常

    Java的异常机制有三种: 一.Error类以及其子类表示的是错误,它是不需要程序员处理也不能处理的异常.比如VirtualMachineError虚拟机错误,ThreadDeath线程僵尸等. 二. ...

随机推荐

  1. SSH原理与运用一:远程登录(转)

    原文:http://www.ruanyifeng.com/blog/2011/12/ssh_remote_login.html 作者: 阮一峰 SSH是每一台Linux电脑的标准配置. 随着Linux ...

  2. LINUX如何查看其他用户的操作

    我们知道可以使用history命令,查看自己的操作记录,但如果你是root用户,如何查看其它用户的操作记录呢?   其实history命令只是把当前用户目录下的~/.bash_History文件内容列 ...

  3. Educational Codeforces Round 1(D. Igor In the Museum) (BFS+离线访问)

    题目链接:http://codeforces.com/problemset/problem/598/D 题意是 给你一张行为n宽为m的图 k个询问点 ,求每个寻问点所在的封闭的一个上下左右连接的块所能 ...

  4. HttpMessageConverter用法

    HttpMessageConverter接口定义 * Strategy interface that specifies a converter that can convert from and t ...

  5. Unity3D之UGUI学习笔记(三):EventSystem

    在UGUI中,EventSystem实现了所有关于交互方面的功能,和NGUI不一样的地方是,我们终于可以摆脱添加Box Collider了! 下面我们来学习一下. 对于按钮来说,直接有onClick的 ...

  6. 关于在Eclipse中使用正则表达式替换的一点记录(使用正则表达式的分组)

    今天在工作中遇到了点替换的麻烦事,由于数据类进行了变动,具体情况是这样的,需要将下面的代码: player.skillData[i].name 替换为: player.skillData.getSki ...

  7. 【数据库】MySql常用函数梳理

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5866388.html MySql常用函数梳理: 1:数学函数 使用格式:一般用于插入.修改语句中,直接 函数( ...

  8. 字符串匹配 - KMP算法

    #include<cstdio> #include<cstring> #include<cstdlib> void GetNext(char *t,int *nex ...

  9. oracle备份恢复之rman恢复到异机

    注意事项: 1 此处实验环境为同平台,同字节序,同版本,源机器和目标机器相同的目录结构. 2 目标机器只需要安装oracle数据库软件即可. 3 第一次利用备份恢复测试环境,之后从源机器拷贝备份到目标 ...

  10. 将Java程序作成exe文件的几种方法【转载】

    看到网上有同志的介绍将Java程序作成exe文件的方法,写的不错,但是也许是这篇文章完成的时间比较早,许多内容已经不合适了.我在这里补充几条: 一.exe4j 说明:exe4j可以将Jar文件制作成e ...