Java 重载、重写和隐藏的区别

前言:
最近复习Java基础时,发现之前有个知识点(隐藏)被我忽略了,一直弄成了覆盖的意思,害,说明基础不够牢固。自己测试了一遍果然发现了隐藏的不一样的地方,这里自己就懒得写总结了,转载别人写的比较好的一篇。

原文:https://www.cnblogs.com/weichunguang/p/7646933.html

一、重载(Overload)

注意:为了正确的区分重载和重写,请各位务必记清重载(Overload)和重写(Override)的英文。

(1)重载定义:表示两个或多个方法的名字相同,但方法的参数不同。方法参数不同有两层含义:A、参数的个数不同;B、参数的类型不同。

[java] view plain copy

public void run(String name, int count)  
{  
System.out.println(count + " " + name + " " + "are running.");  
}  
public void run(int count, String name)  
{  
System.out.println(count + " " + name + " " + "are running.");  
}  

请思考以上两个方法是否构成了重载?

(2)重载发生的时机:重载是发生在同一个类内部的两个或多个方法之间。

(3)方法的返回类型对重载没有任何影响!即,对于方法名字和参数都相同的两个方法,如果他们的返回类型不同,这种语法格式是错误的,大家可以试一试。那么,也就是说,只要是重载返回类型一定相同。否则为两个不同的方法。如下代码,这是两个不同的方法。

[java] view plain copy

public void run()  
{  
System.out.println("dog is running");  
}  
public int run(String name, int count)  
{  
System.out.println(count + " " + name + " " + "are running.");  
return 1;  
}  

(3)构造方法之间的重载:一个类中有多个构造方法,那么它们一定是重载的。

(4)重载方法之间的调用:对于普通方法的重载,重载的方法之间是可以直接调用的,如下代码一。

但是对于重载的构造方法之间的调用,需要使用this()关键字。A、this()括号中参数表示目标构造方法所接收的参数;B、对this()的调用必须是构造方法的第一条语句。如下代码二。

public int run(String name, int count)  
{  
System.out.println(count + " " + name + " " + "are running.");  
return 1;  
}  
public void run(int count, String name)  
{  
run(name , count);  
System.out.println(count + " " + name + " " + "are running.");  
}  



public Dog()  
{  
this("金巴");  
System.out.println("你好世界,我是一条狗!");  
}  
public Dog(String name)  
{  
System.out.println("你好世界," + "我是一条" + name + "狗!");  
}  

二、重写(Override)

(1)重写定义:子类与父类的方法的返回类型一样,方法名称一样,参数一样,这样我们就说子类与父类的方法构成了重写关系。

补充:在重写中,我们一直没提到权限的问题(public、protected、private),使用private修饰的方法是不能够进行重写的,也不能够被继承,所以private和多态扯不上关系。在同一个包下,构成重写关系,父类和子类的方法,权限可以是public和public、protected和protected、protected和public,但不可能是public和protected,即权限可以扩大但不可缩小。

(2)重写发生的时机:重写发生在父类与子类之间。

(3)构造方法时不能重写的,如果您理解是构造方法的作用,就知道构造方法为什么不能重写。

(4)在重写时,子类重写的方法调用父类被重写的方法时,可以使用super.父类方法的方式调用,其中此语句不必放在第一行。如下代码所示:

class Animal  
{  
public void run()  
{  
System.out.println("animal is running");  
}  
}  
class Dog extends Animal  
{  
//override  
public void run()  
{  
System.out.println("dog is running");  
super.run();  
}  
}  

三、隐藏(Hide)

(1)提到隐藏,就不得不提到一个关键字–static,static是静态的意思,具体用法意义,各位可以去查相关的资料。这里我想说的,static方法在继承中的特殊性!
(1)子类不能重写(Overriding)父类的静态方法,只能隐藏(Hiding)父类的静态方法。

(2)什么叫隐藏父类的静态方法呢?就是说父类的静态方法和子类的静态方法是同时存在的,具体调用的是哪个方法,是要看调用的方法的引用是什么类型的引用,如果是父类型的引用,调用的就是父类的静态方法,如果是子类型的引用,调用的就是子类的静态方法。【这里面有些多态(Polymorphism)的知识,不懂的可以问我哈!】具体区别我们可以看一个例子,这个例子来自官方文档。

public class Animal   
{  
public static void testClassMethod()   
{  
System.out.println("The class" + " method in Animal.");  
}  
public void testInstanceMethod()   
{  
System.out.println("The instance " + " method in Animal.");  
}  
}  

The second class, a subclass of Animal, is called Cat:

public class Cat extends Animal   
{  
public static void testClassMethod()   
{  
System.out.println("The class method" + " in Cat.");  
}  
public void testInstanceMethod()  
{  
System.out.println("The instance method" + " in Cat.");  
}  
public static void main(String[] args)   
{  
Cat myCat = new Cat();  
Animal myAnimal = myCat;  
Animal.testClassMethod();  
myAnimal.testInstanceMethod();  
}  
}  

隐藏:父类和子类拥有相同名字的属性或者方法时,父类的同名的属性或者方法形式上不见了,实际是还是存在的。

隐藏现象发生在子类和父类之间,隐藏是针对父类中成员变量和静态方法而言。

当子类声明与父类中成员变量具有相同的变量名的变量时,则实现了对父类中成员变量的隐藏;

当子类声明了与父类中的静态成员方法具有相同的方法名,参数列表和相同的返回值时,则实现了对父类中静态方法的隐藏。

注意:当发生隐藏的时候,声明类型是什么类,就调用对应类的属性或者方法,而不会发生动态绑定

方法隐藏只有一种形式,就是父类和子类存在相同的静态方法

属性只能被隐藏,不能被覆盖

子类实例变量/静态变量可以隐藏父类的实例/静态变量,总结为变量可以交叉隐藏

隐藏和覆盖的区别

被隐藏的属性,在子类被强制转换成父类后,访问的是父类中的属性

被覆盖的方法,在子类被强制转换成父类后,调用的还是子类自身的方法

因为覆盖是动态绑定,是受RTTI(run time type identification,运行时类型检查)约束的,隐藏不受RTTI约束,总结为RTTI只针对覆盖,不针对隐藏

特殊情况:

1.final修饰的属性可以被隐藏,但是不能被赋值,即不能用=来赋值,网上说final属性不能被修改,这个说法不准确,因为对于引用类型的变量用final修饰后,它只是不能被指向其他对象,但是可以改它自身的值,可以用ArrayList测试,final属性可以在运行的时候进行初始化,但是不能不出现初始化语句

2.final修饰的方法不能被覆盖,可以被重载

3.final修饰的类不能被继承

4.private 方法隐式添加了final

实例:

SuperClass类:

package com.yilong.test.scjp;  

    public class SuperClass {  
    public static int i = 1;  
    public int j = 2;  
    public final int k = 3;  
    public static void method1() {  
    System.out.println("SuperClass Method1");  
    }  
    public void method2() {  
    System.out.println("SuperClass Method2");  
    }  
    public final void method3() {  
    System.out.println("SuperClass Method3");  
    }  
    }  
  • 1
    点赞
  • 3
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:精致技术 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值