重载与重写规则

重载与重写规则_第1张图片

public class playable {

}
class Parent2 { public Parent2 getObject() { return new Child() ; } }
class Child extends Parent2 {
@Override
public Child getObject() {
return new Child();
}
//jdk1.5之后,返回类型可以不一样,但是必须是父类返回类型的之类才行所以返回类型待定版本问题
}

方法的重写(Overriding)和重载(Overloading)是java多态性的不同表现,重写是父类与子类之间多态性的一种表现,重载可以理解成多态的具体表现形式。

(1)方法重载是一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,则称为方法的重载(Overloading)。
(2)方法重写是在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法,就称为重写(Overriding),对子类的要求:更public更少错误
(3)方法重载是一个类的多态性表现,而方法重写是子类与父类的一种多态性表现。
final和static都不能被重写、重载,父类的private方法不能重写,

重写规则:
1、访问修饰符的限制一定要不小于被重写方法的访问修饰符

    比如:Object类有个toString()方法, 开始重写这个方法的时候我们总容易忘记Public修饰符, 出错的原因就是:没有加任何访问修饰符的方法具有包访问权限, Default访问权限小于Public访问权限, 所以编译器出错。

2、 参数列表必须与被重写方法的相同。
重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。

3、C-1:返回类型必须与被重写方法的返回类型相同。
父类方法A:void catch(){} 子类方法 B:int catch(){} 两者虽然参数相同, 返回类型不同, 所以不是重写。
父类方法A:int catch(){} 子类方法 B:long catch(){} 返回类型虽然兼容父类, 但是不同就是不同, 所以不是重写。

     C-1補足1:  如果在没有加注@Override的情况下, 方法名和参数列表完全相同,且满足规则A的情况下, 返回值类型必须完全一致的情况下、才不会出现编译错误(即为该方法为强制重写方法)。如果以上条件中参数列表不同,且返回值类型不同这样编译并不会出现错误(这个方法为在子类的新方法,且不是重写方法)。// 2016/11/21 19:44 bluetata 追記标注補足1(下接博文后追記)

C-1補足2:  当子类的方法重写或实现父类的方法时, 方法的后置条件(即方法的返回值)要比父类更严格。[参照2]// 2016/11/22 追記

即:如果重写方法的参数列表和方法名相同,且其他条件满足的情况下,方法的返回值为父类的子类,那么该方法也为重写方法

4 重写方法不能抛出新的异常或者比被重写方法声明的检查异常更广的检查异常。但是可以抛出更少,更有限或者不抛出异常。

举个简单的例子:父类异常好比父亲偷盗抢掠、那么儿子不能比父亲更坏、要学好、自然异常就要少。虽然举得例子与社会主义核心价值观有冲突、但是比较形象。// 

5、 如果一个方法不能被继承, 则不能重写它。
比较典型的就是父类的private方法。因为private说明该方法对子类是不可见的, 子类再写一个同名的方法并不是对父类方法进行复写(Override), 而是重新生成一个新的方法, 也就不存在多态的问题了。同理也可以解释final, 因为方法同样是不可覆盖的。
6、不能重写被标识为final、static的方法。
final方法可以被继承, 但是不能被重写, 一个方法如果被final修饰, 那么也就意味着, 这个方法不会被改动(声明一个final方法的主要目的是防止方法的内容被修改)。

《JAVA编程思想》中多次的提到:方法是静态的、他的行为就不具有多态性。静态方法是与类、而非单个对象相关联的。

父类的普通方法可以被继承和重写,不多作解释,如果子类继承父类,而且子类没有重写父类的方法,但是子类会有从父类继承过来的方法。静态的方法可以被继承,但是不能重写。如果父类中有一个静态的方法,子类也有一个与其方法名,参数类型,参数个数都一样的方法,并且也有static关键字修饰,那么该子类的方法会把原来继承过来的父类的方法隐藏,而不是重写。通俗的讲就是父类的方法和子类的方法是两个没有关系的方法,具体调用哪一个方法是看是哪个对象的引用;这种父子类方法也不在存在多态的性质。《JAVA编程思想》:只有普通的方法调用可以是多态的,静态方法是与类而不是与某个对象相关联。

  父类的静态方法不能被子类覆盖为非静态方法。

   子类可以定义与父类的静态方法同名的静态方法、以便在子类中**隐藏**父类的静态方法(满足覆盖约束)、而且Java虚拟机把静态方法和所属的类绑定、而把实例方法和所属的实例绑定。

   如果在上记的方法上**追记@Override注解**的话、该方法会出**编译错误**。因为该方法实际**不是重写方法。**

補足2:父类的非静态方法不能被子类覆盖为静态方法。

補足3:面试可能会遇到的此处相关问题(与静态相关)

            1、abstract方法能否被static修饰?

                      不能被static修饰, 因为抽象方法要被重写、而static和子类占不到边、即上述。// 2016/12/06 20:59 bluetata 追記
                    反过来也一样static方法一定不能被abstract方法修饰, static不属于对象而属于类,  static方法可以被类直接调用(抽象方法需要被实例才能被调用, 这里说的实例是实现的意思,也就是重写后实现其方法), 这样注定了static方法一定有方法体, 不能是没有方法体的抽象方法(被abstract修饰)  // 2018/07/10 18:17 bluetata 追記

            2、为什么静态方法不能被覆盖? // 2016/12/15 午后 追記

      可以参看上面从java编程思想摘出的话、另外在总结下:覆盖依赖于类的实例,而静态方法和类实例并没有什么关系。而且静态方法在编译时就已经确定,而方法覆盖是在运行时确定的(动态绑定)(也可以说是java多态体现在运行时、而static在编译时、与之相悖)。

            3、构造方法能否被重写、为什么? // 2016/12/15 晚 追記

      不能、构造方法是隐式的static方法、同问题2。其实这个问题回答切入点很多、首先构造方法无返回值、方法名必须和所在类名相同、这一点就必杀了子类无法重写父类构造方法。另外多态方面、重写是多态的一种提现方式、假设在子类重写了构造方法是成立的、那么子类何谈实例成父类。另外重要得一点、子类可以使用super()调用父类的构造方法、且必须放在子类构造方法内的第一行。 请参看另一篇博文: <>

              4、静态方法为什么不能访问非静态变量或方法?  // 2018/07/10 午后追记
                      对于前面123问题理解后, 问题4也不难理解, 还是引用下《JAVA编程思想》:静态方法是与类而不是与某个对象相关联  用static修饰的成员属于类, 非static修饰的成员属于实例对象, 也就是类可以直接调用静态成员, 这样假设如果类直接调用了静态成员, 而静态成员调用了非静态变量或方法, 这样在内存中是找不到该非静态变量方法的, 因为静态方法需要创建对象后才可调用.
                     另外通过类加载说明: 类的加载全过程:加载->验证->准备->解析->初始化 在这里加载到解析阶段都是JVM进行主导,而在初始化阶段才是真正java执行代码的阶段. static成员在初始化阶段之前会被加载到方法区中, 并且进行初始化赋值等操作,并且分配内存, 而非static成员确是在加载后解析后的初始化阶段才会被"加载"分配内存, 也就是代码中使用new进行创建实例的时候, 这样也就验证了 类可以直接调用static成员没有问题, 而直接调用非static的成员就会出问题, 因为违背了java加载初始化的逻辑.

注意: 如果static调用非static成员 编译器会出现 No enclosing instance of type * is accessible 异常错误.

XX01、重写规则補足:

補足1:父类的抽象方法可以被子类通过两种途径覆盖(即实现和覆盖)。

補足2:父类的非抽象方法可以被覆盖为抽象方法[2]。

      [2]子类必须为抽象类。



**重载的三个条件:**

1.在同一个类中
2.方法名必须相同
3.方法的参数列表不同   (和返回值类型没有关系,可以相同也可以不相同。)(形参类型和个数不一样,顺序不同)
4、声明为final、static的方法不能被重载。

仅仅参数变量名称不同是不可以的。
跟成员方法一样,构造方法(构造器)也可以重载。

声明为static的方法不能被重载,但是能够被再次声明。
方法重载是让类以统一的方式处理不同类型数据的一种手段。

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

方法的重载的规则:
方法名称必须相同。
参数列表必须不同(个数不同、或类型不同、参数排列顺序不同等)。
方法的返回类型可以相同也可以不相同。
仅仅返回类型不同不足以成为方法的重载。

方法重载的实现:
方法名称相同时,编译器会根据调用方法的参数个数、参数类型等去逐个匹配,以选择对应的方法,如果匹配失败,则编译器报错,这叫做重载分辨。

你可能感兴趣的:(笔记,JAVA)