java中重载(overloading)与重写(overriding)

常见面试题是关于重载(overloading)方法和重写(overriding)方法的。

 代码如下 复制代码

 public class MethodOverrideVsOverload {
 
  public boolean equals( MethodOverrideVsOverload other ) {
      System.out.println("MethodOverrideVsOverload equals method reached" );
      return true;
    }
 
  public static void main(String[] args) {
   Object o1 = new MethodOverrideVsOverload();
   Object o2 = new MethodOverrideVsOverload();
 
   MethodOverrideVsOverload o3 = new MethodOverrideVsOverload();
   MethodOverrideVsOverload o4 = new MethodOverrideVsOverload();
 
   if(o1.equals(o2)){
    System.out.println("objects o1 and o2 are equal");
   }
 
   if(o3.equals(o4)){
    System.out.println("objects o3 and o4 are equal");
   }
  }
 }

A.输出结果是:

MethodOverrideVsOverload equals method reached

objects o3 and o4 are equal

这个问题考察了哪些概念呢?

•Java语言中,一个类只能从一个类中继承出来(也就是,单继承结构),如果没有显式的标明所继承自的类,那么自动继承自Object对象。
•大多数的非final对象类方法都会被子类重写(overridden):
public boolean equals(Object obj); // make note of this method

public int hashCode();

public String toString();

•重载方法在编译时起作用(例如,静态绑定),重写方法在运行时起作用(例如,动态绑定)。静态绑定意味着JVM在编译时决定调用的类或方法。而动态绑定时,JVM是在运行时决定调用的类或方法。动态绑定设计是多态的基础。更多了解编译时和运行时.
•子类中重写父类的对应方法必须遵循下面的规则:
参数 不可变(译者注:包括参数类型和个数)。
返回类型 不可变,除了协变返回类型或其子类型(covariant (subtype) returns)。
异常 子类中可以抛出更少的异常,但绝对不能抛出父类中没有定义的已检查异常。
访问权限 比父类中对应方法更宽松。
调用 运行时(也就是动态绑定),根据对象类型来决定调用的具体方法。

现在,再回头看上面的代码,MethodOverrideVsOverload 类中的”equals(MethodOverrideVsOverload other)” 方法并没有重写Object类中的”public boolean equals(Object obj)” 方法。这是因为其违背了参数规则,其中一个是MethodOverrideVsOverload 类型,而另一个是Object类型。因此,这两个方法是重载关系(发生在编译时),而不是重写关系。

因此,当调用o1.equals(o2)时,实际上调用了object类中的public boolean equals(Object obj)方法。这是因为在编译时,o1和o2都是Object类型,而Object类的equals( … )方法是比较内存地址(例如,Object@235f56和Object@653af32)的,因此会返回false。

当调用o3.equals(o4)时,实际上调用了MethodOverrideVsOverload 类中的equals( MethodOverrideVsOverload other )方法。这是因为在编译时,o3和o4都是MethodOverrideVsOverload类型的,因此得到上述结果。

接下来还可以怎么提问呢?

Q.那怎么解决上面的那个问题呢?

A.在Java5中,新增了注解,其中包括很好用的编译时注解(compile time annotations)@override,来保证方法正确的重写了父类方法。如果在上面的代码中添加了注解,那么JVM会抛出一个编译错误。

因此,解决的方法就是给MethodOverrideVsOverload  类的boolean equals( MethodOverrideVsOverload other )方法添加@override注解。这样的话编译时就会有错误抛出来提示开发者某个方法没有正确的重写父类方法。之后,还需要修改方法的参数,将其从 Object变成MethodOverrideVsOverload,具体如下:

 代码如下 复制代码

View Code
 public class MethodOverrideVsOverload {
 
  @Override
  public boolean equals( Object other ) {
      System.out.println("MethodOverrideVsOverload equals method reached" );
      return true;
  }
 
  public static void main(String[] args) {
   Object o1 = new MethodOverrideVsOverload(); //during compile time o1 is of type Object
                                               //during runtime o1 is of type MethodOverrideVsOverload
   Object o2 = new MethodOverrideVsOverload(); //during compile time o2 is of type Object
                                               //during runtime o2 is of type MethodOverrideVsOverload
 
   MethodOverrideVsOverload o3 = new MethodOverrideVsOverload(); //o3 is of type MethodOverrideVsOverload
                                                                 // during both compile time and runtime
   MethodOverrideVsOverload o4 = new MethodOverrideVsOverload(); //o4 is of type MethodOverrideVsOverload
                                                                 // during both compile time and runtime
 
   if(o1.equals(o2)){
    System.out.println("objects o1 and o2 are equal");
   }
 
   if(o3.equals(o4)){
    System.out.println("objects o3 and o4 are equal");
   }
 
  }
 
 }

输出为:

 代码如下 复制代码

MethodOverrideVsOverload equals method reached

objects o1 and o2 are equal

MethodOverrideVsOverload equals method reached

objects o3 and o4 are equal

时间: 2024-10-07 11:59:17

java中重载(overloading)与重写(overriding)的相关文章

实例分析java中重载与重写的区别_java

本文以实例详细分析了Java中重载与重写的区别,感兴趣的朋友可以参考一下. 一.重载(Overloading): (1) 方法重载是让类以统一的方式处理不同类型数据的一种手段.多个同名函数同时存在,具有不同的参数个数/类型. 重载Overloading是一个类中多态性的一种表现. (2)Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义. 调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法, 这就是多态性. (3) 重载的时候,方

java 中重载函数调用时出现的问题

Java 中重载函数很常见,比如JDK 中的的FileInputStream构造方法就有重载: FileInputStream(File file)  FileInputStream(String name) 但是有时候会出现如下问题:  报错信息为:The method write2File(boolean, File) is ambiguous for the type TestOverride   出现该问题的场景是:重载的两个函数中有实参为null,java编译器没法确定此处的null是

java中重载,继承,重写和多态的区别_java

重载,继承,重写和多态的区别: 1)继承是子类获得父类的成员. 2)重写是继承后重新实现父类的方法. 3)重载是在一个类里一系列参数不同名字相同的方法. 4)多态则是为了避免在父类里大量重载引起代码臃肿且难于维护. 网上看到一个有趣的说法是:继承是子类使用父类的方法,而多态则是父类使用子类的方法. 下面的例子包含了这四种实现: class Triangle extends Shape {  public int getSides() {   return 3;  }} class Rectang

java中重载、覆盖和隐藏三者的区别分析_java

重载:方法名相同,但参数不同的多个同名函数 注意:1.参数不同的意思是参数类型.参数个数.参数顺序至少有一个不同 2.返回值和异常以及访问修饰符,不能作为重载的条件(因为对于匿名调用,会出现歧义,eg:void a ()和int a() ,如果调用a(),出现歧义) 3.main方法也是可以被重载的 覆盖:子类重写父类的方法,要求方法名和参数类型完全一样(参数不能是子类),返回值和异常比父类小或者相同(即为父类的子类),访问修饰符比父类大或者相同 两同两小一大  注意:子类实例方法不能覆盖父类的

关于Java中重载的若干问题

一.问题引入 今天看视频时偶然间看到了,说父类和子类间也可以重载,貌似和以前的观念有些冲突,就验证了下-- 二.问题解决 看如下代码: public class Son extends Father { public void test(int i) { System.out.println("我是子类里的有参数test方法:"+i); } public static void main(String[] args) { Son son = new Son(); son.test();

Java中继承、多态、重载和重写介绍_java

什么是多态?它的实现机制是什么呢?重载和重写的区别在那里?这就是这一次我们要回顾的四个十分重要的概念:继承.多态.重载和重写. 继承(inheritance) 简单的说,继承就是在一个现有类型的基础上,通过增加新的方法或者重定义已有方法(下面会讲到,这种方式叫重写)的方式,产生一个新的类型.继承是面向对象的三个基本特征--封装.继承.多态的其中之一,我们在使用JAVA时编写的每一个类都是在继承,因为在JAVA语言中,java.lang.Object类是所有类最根本的基类(或者叫父类.超类),如果

怎样很好的将java中的构造重载学好(初学者)

问题描述 怎样很好的将java中的构造重载学好(初学者) 现在初学,但是在写代码的时候总是无法使用构造重载这种方法,并且在写代码的时候老是思绪混乱应该怎莫办??????? 解决方案 java允许在一个类中,多个方法拥有相同的名字,但在名字相同的同时,必须有不同的参数,这就是重载,编译器会根据实际情况挑选出正确的方法,如果编译器找不到匹配的参数或者找出多个可能的匹配就会产生编译时错误,这个过程被称为重载的解析 1 普通方法的重载 普通方法的重载是Java实现多态技术的重要手段,为编程带来了很多便利

JAVA学习(七):方法重载与方法重写、this关键字和super关键字

方法重载与方法重写.this关键字和super关键字 1.方法重载 重载能够使具有相同名称但不同数目和类型参数的类传递给方法. 注: 一是重载方法的参数列表必须与被重载的方法不同,并且这种不同必须足以清楚地确定要调用哪一个方法: 二是重载方法的返回值类型可以与被重载的方法相同,也可以不同,但是只有返回值类型不同不能表示为重载. 例如,最常用的println()方法在JDK的java.io.PrintStream中定义了十几种形式的重载,常用格式如下: public void println(in

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

这篇文章讨论了Java面向对象概念中一个基本的概念–Field Hiding(隐藏成员变量) 在讨论这个问题之前,我们看一段特别特别简单的代码,请问一下方法的数据结果是什么? /**   * @author Hollis 17/9/27.   */  public class FieldOverriding {        public static void main(String[] args) {          Sub c1 = new Sub();          System.