建议6:覆写变长方法也循规蹈矩

在Java中,子类覆写父类中的方法很常见,这样做既可以修正Bug也可以提供扩展的业务功能支持,同时还符合开闭原则(Open-Closed Principle),我们来看一下覆写必须满足的条件:

1.重写方法不能缩小访问权限。

2.参数列表必须与被重写方法相同。

3.返回类型必须与被重写方法的相同或是其子类。

4.重写方法不能抛出新的异常,或者超出父类范围的异常,但是可以抛出更少、更有限的异常,或者不抛出异常。

 public class Client {
public static void main(String[] args) {
//向上转型
Base base = new Sub();
base.fun(100, 50);
//不转型
Sub sub = new Sub();
sub.fun(100, 50);
//编译报错 The method fun(int, int[]) in the type Sub is not applicable for the arguments (int, int)
}
}
//基类
class Base{
void fun(int price,int... discounts){
System.out.println("Base......fun");
}
} //子类,覆写父类方法
class Sub extends Base{
@Override
void fun(int price,int[] discounts){
//Varargs methods should only override or be overridden
//by other varargs methods unlike Sub.fun(int, int[]) and Base.fun(int, int...)
System.out.println("Sub......fun");
}
}

请问:该程序有问题吗?—编译通不过。那问题出在什么地方呢?

@Override注解吗?非也,覆写是正确的,因为父类的calPrice编译成字节码后的 形参是一个int类型的形参加上一个int数组类型的形参,子类的参数列表也与此相同,那覆写是理所当然的了,所以加上@Override注解没有问题, 只是Eclipse会提示这不是一种很好的编码风格。

难道是“sub.fun(100, 50)”这条语句?正解,确实是这条语句报错,提示找不到fun(int,int)方法。这太奇怪了:子类继承了父类的所有属性和方法,甭管是私有的还是 公开的访问权限,同样的参数、同样的方法名,通过父类调用没有任何问题,通过子类调用却编译通不过,为啥?难道是没继承下来?或者子类缩小了父类方法的前 置条件?那如果是这样,就不应该覆写,@Override就应该报错,真是奇妙的事情!

事实上,base对象是把子类对象Sub做了向上转型,形参列表是由父类决定的,由于是变长参 数,在编译时,“base.fun(100, 50)”中的“50”这个实参会被编译器“猜测”而编译成“{50}”数组,再由子类Sub执行。我们再来看看直接调用子类的情况,这时编译器并不会把 “50”做类型转换,因为数组本身也是一个对象,编译器还没有聪明到要在两个没有继承关系的类之间做转换,要知道Java是要求严格的类型匹配的,类型不 匹配编译器自然就会拒绝执行,并给予错误提示。

这是个特例,覆写的方法参数列表竟然与父类不相同,这违背了覆写的定义,并且会引发莫名其妙的错误。所以读者在对变长参数进行覆写时,如果要使用此类似的方法,请找个小黑屋仔细想想是不是一定要如此。

注意 覆写的方法参数与父类相同,不仅仅是类型、数量,还包括显示形式。

[改善Java代码]覆写变长方法也循规蹈矩的更多相关文章

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

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

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

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

  3. [改善Java代码]避免带有变长参数的方法重载

    建议4: 避免带有变长参数的方法重载 在项目和系统的开发中,为了提高方法的灵活度和可复用性,我们经常要传递不确定数量的参数到方法中,在Java 5之前常用的设计技巧就是把形参定义成Collection ...

  4. [改善Java代码]用枚举实现工厂方法模式更简洁

    工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...

  5. [改善Java代码]自由选择字符串拼接方法

    对一个字符串拼接有三种方法:加号,contact方法,StringBuffer或者StringBuilder的append方法,其中加号是最常用的.其他两种方式偶尔会出现在一些开源项目中,那么这三者有 ...

  6. [改善Java代码]别让null值和空值威胁到变长方法

    建议5:别让null值和空值威胁到变长方法 public class Client { public void methodA(String str,Integer... is){ } public ...

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

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

  8. [改善Java代码]让多重继承成为现实

    建议41: 让多重继承成为现实 在Java中一个类可以多重实现,但不能多重继承,也就是说一个类能够同时实现多个接口,但不能同时继承多个类.但有时候我们确实需要继承多个类,比如希望拥有两个类的行为功能, ...

  9. 使用第三方工具覆写Object中方法

    我们在实际开发中,经常需要覆写Object中的equals,hashcode,toString方法,其实编写这些代码并不是很难,但很枯燥和乏味. 下面推荐Google的Guava jar包来覆写上面的 ...

随机推荐

  1. Spark RDD概念学习系列之RDD与DSM的异同分析(十三)

    RDD是一种分布式的内存抽象,下表列出了RDD与分布式共享内存(Distributed Shared Memory,DSM)的对比. 在DSM系统[1]中,应用可以向全局地址空间的任意位置进行读写操作 ...

  2. 最大连续子数组问题2-homework-02

    1) 一维数组最大连续子数组 如第homework-01就是一维数组的最大子数组,而当其首位相接时,只需多考虑子数组穿过相接的那个数就行了! 2)二维数组 算法应该和第一次的相似,或者说是将二维转化为 ...

  3. NSLog说明

    %@ 对象 %d,%i 整型 (%i的老写法) %hd 短整型 %ld , %lld 长整型 %u 无符整型 %f 浮点型和double型 %0.2f 精度浮点数,只保留两位小数 %x,%X 二进制整 ...

  4. UVALive 7454 Parentheses (栈+模拟)

    Parentheses 题目链接: http://acm.hust.edu.cn/vjudge/contest/127401#problem/A Description http://7xjob4.c ...

  5. 搭建nodejs环境推荐用两个工具:nvm和npm

    nvm 是 nodejs version manager 的简称,即:nodejs版本管理npm 是 nodejs package manager 的简称,即:nodejs模块管理 有了这两个工具,管 ...

  6. Light oj 1138 - Trailing Zeroes (III) (二分)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1138 题目就是给你一个数表示N!结果后面的0的个数,然后让你求出最小的N. 我们可以知 ...

  7. 【BJG吐槽汇】第一期 - 警惕亚马逊莫名自动扣款!千万不要进了它的坑!

    BJG吐槽汇:一直以来我都觉得其实生活中工作中会有各种各样奇葩的事或者奇葩的人可以去吐槽,那么BeJavaGod本身聊得就是关于JavaWeb技术,互联网技术,互联网产品等,那么今天起咱们开了这么一档 ...

  8. NOSQL之旅---HBase

    最近因为项目原因,研究了Cassandra,Hbase等几个NoSQL数据库,最终决定采用HBase.在这里,我就向大家分享一下自己对HBase的理解. 在说HBase之前,我想再唠叨几句.做互联网应 ...

  9. EcTouch二次开发

    一.EcTouch简介 1.1. 什么是ECTOUCH ECTouch是上海商创网络科技有限公司推出的一款开源免费移动商城网店系统,可以在手机上面卖商品的电子商务软件系统.能够帮助企业和个人快速构建手 ...

  10. Linux - CentOS 6.3 (x86_64)安装过程详细图解

    I:下载CentOS 6.3 楼主已经从CentOS官方公布下载列表当中整理出了2个在国内的下载地址,这样就不需要为访问墙外的龟速网络而费心了. 32位:下载地址1,下载地址2 64位:下载地址1,下 ...