首页 > 其他分享 >重载

重载

时间:2023-04-24 23:44:35浏览次数:35  
标签:methodForOverload 参数 重载 Integer 方法 public

       在同一个类中,如果多个方法有相同的名字、不同的参数,即称为重载,比如一个类中有多个构造方法。String类中的valueOf也是比较著名的案例,它有9个方法,可以将输入的基本数据类型、数组、Object等转化成为字符串。在编译器的眼里,方法名称+参数类型+参数个数,组成一个唯一键,称为方法签名,JVM通过这个唯一键决定调用哪种重载的方法。注意,方法返回值并非是这个组合体中的一员,所以在使用重载机制时,不能有两个方法名称完全相同,参数类型和个数也相同,但是返回类型不同的方法。如下示例代码:

 public class SameMethodSignature {

    public void methodForOverload() {}
   
    // 编译出错,返回值并不是方法签名的一部分
    public final int methodForOverload() {
      return 7;
   }
  
   //编译出错,访问控制符也不是方法签名的一部分
   private void methodForOverload() {}

   // 编译出错,静态标识符也不是方法签名的一部分
   public static void methodForOverload() {}

   // 编译出错,final标识符也不是方法前面的一部分
  public final void methodForOverload(){} 
}

    重载似乎是比较容易理解和掌握的变成技能,有时仅凭肉眼判断就能知道应调用哪种重载方法,特别是如下代码所示的第一种方法和第二种方法。前者是无参的,后者参数是int param,但是后边的三种方法,只是参数类型不同罢了。这时,如果调用methodForOverload(7),猜猜,到底调用的是谁呢?

  public class OverloadMethods {

   // 第一种方法:无参
   public void overloadMethod() {
    System.out.println("无参方法")
   }
  
  // 第二种方法:基本数据类型
  public void methodForOverload(int param) {
   System.out.println("参数为基本类型的int方法");
 }

 // 第三种方法:包装数据类型
 public void methodForOverload(Integer param) {
   System.out.println("参数为包装类型的Integer方法");
 }

 // 第四种方法:可变参数,可以接受0-n个Integer对象
 public void methodForOverload(Integer ...param) {
    System.out.println("可变参数方法");
 }  

 // 第五种方法:Object对象
 public void methodForOverload(Object param) {
  System.out.println("参数为Object方法");
 }
}

     先看这五种方法的字节签名有何异同点。

 // V表示Void返回值
public overloadMethod() V

// I就是代表int基本数据类型,而非Integer
public methodForOverload(I) V

// L表示输入的参数是对象,然后跟着package+类名 (第一处)
public methodForOverload(Ljava/lang/Integer;) V

// varargs 表示可变参数 (第二处)
public varargs methodForOverload(Ljava/lang/Integer;) V

// L同样表示对象参数
public methodForOverload(Ljava/lang/Object;) V

第一处与第二处的区别是后者加了varargs标识,即可变参数,参数个数可以是0或者多个,也就是说,它和第一、二、三个方法都是有可能会争抢地盘的。首先,如果调用methodForOverload(),假如在无参方法缺席的情况下,也会调用到可变参数方法。但是如果无参方法在场,就不需要可变参数了。现在对这个类来说,methodForOverload(7)到底花落谁家?JVM在重载方法中,选择合适的目标方法的顺序如下:
  (1)精确匹配
  (2)如果是基本数据类型,自动转换成更大表示范围的基本类型
  (3)通过自动的拆箱与装箱
  (4)通过子类向上转型继承路线依次匹配
  (5)通过可变参数匹配
    精确匹配优先,这是毫无疑问的。int在和Integer的较量中胜出,因为不需要自动装箱,所以7会调用int参数的方法。如果是new Integer(7)的话,Integer参数的方法胜出。
  如果本方法只有methodForOverload(long),则可以接受methodForOverload(3)的实参调用;反之,如果只有methodForOverload(int),而传入long值,则会编译出错。基本数据类型转为表示范围更大的基本数据类型优先于自动装箱,即int转为long,优先于装箱为Integer。
  注意,null可以匹配任何类对象,在查找目标方法时,是从底层子类依次向上查找的。在本类中,如果methodForOverload(null),则会调用参数为Integer的方法。第一,因为Integer是一个类;第二,它是Object的子类。在示例代码中,如果还有单个String类型的方法,则会编译出错,因为null不知道该选择Integer还是String。
  根据上述匹配顺序,可变参数在竞争中明显处于弱势地位。如果调用methodForOverload(13,14),此时有两个参数,虽然有自动装箱的开销,但可变参数仍会执行这种方法请求。
    最后,有些程序员好奇心特别强,刚才不是说7是匹配基本数据类型优先,而 new Integer(7)是匹配包装类优先的,那如果这样定义:

 public void methodForOverload(int param1,Integer param2) {}
 public void methodForOverload(Integer param3,int param4) {}

  这种定义方式就是在考验编译器的忍耐底线,虽然编译器的内心是崩溃的,但是这样的定义是可以通过编译的,这也是一种重载方式。但是调用methodForOverload(13,14)会彻底让编译器失控。
  最后,假如一个类只有mehotdForOverload(Object param)和methodForOverload(Integer ...param)两种方法,根据目标方法匹配顺序,methodForOverload(7)会自动装箱,然后向上转向,遇到Object。这个规则优先于调用可变参数的重载方法。
  父类的公有实例方法与子类的公有实例方法可以存在重载关系。不管继承关系如何复杂,重载在编译时可以根据规则知道调用哪种目标方法。所以,重载又称为静态绑定。

标签:methodForOverload,参数,重载,Integer,方法,public
From: https://www.cnblogs.com/ganjing/p/17348125.html

相关文章

  • 函数重载
    函数重载是指在同一作用域内,可以有一组具有相同函数名,不同参数列表的函数,这组函数被称为重载函数。重载函数通常用来命名一组功能相似的函数,这样做减少了函数名的数量,避免了名字空间的污染,对于程序的可读性有很大的好处。#include<iostream>usingnamespacestd;voidprint(i......
  • 7、带输入的复数类-加-减-乘运算符重载
    如题,要求实现:1、复数类含两个参数的构造函数,一个为实部,一个为虚部。2、实现-加-减-乘运算符重载运算符重载功能,并实现返回值为复数类。3、Show出结果。例如输入78输出:(10+12i)(-4-4i)(-11+52i)#include<iostream>usingnamespacestd;classCmycomplex{private:......
  • 6、带输入的复数类加法运算符重载
    如题,要求实现:1、复数类含两个参数的构造函数,一个为实部,一个为虚部。2、实现加法运算符重载功能,并实现返回值为复数类。3、Show出结果。#include<iostream>usingnamespacestd;classCmycomplex{private:doublereal,imag;public:Cmycomplex(doubler=0,doubl......
  • 5、复数类加法运算符重载
    如题,要求实现:1、复数类含两个参数的构造函数,一个为实部,一个为虚部。2、实现加法运算符重载功能,并实现返回值为复数类。3、Show出结果。#include<iostream>usingnamespacestd;classCmycomplex{private:intreal,imag;public:Cmycomplex(intr=0,inti=0);//......
  • 运算符重载"+""-""*"“<<”">>"
    一、问题描述。设计一个描述三维坐标的向量类vector3D,成员如下:数据成员:三个坐标x,y,z,float类型,私有访问属性公有函数成员:三个参数均有默认值的构造函数,默认值为0,0,0;重载输入输出运算符,输出格式为(x, y, z);重载加法+、减法-、数乘*(乘数在前,乘数为float类型)这三个运算符;在主函数中定......
  • C#基础 ref out 函数参数 不算重载的简单示例
     .NETFramework:4.7.2       IDE:VisualStudioCommunity2019        OS:Windows10x64    typesetting:Markdown codeusingSystem;namespaceConsoleApp{classProgram{staticvoidMain(string[]args){......
  • 打卡 复数的加减运算(运算符重载)
    ###复数加减(运算符重载)声明一个复数类CComplex(类私有数据成员为double型的real和image)定义构造函数,用于指定复数的实部与虚部。重载<<运算符,以格式real+imagei的格式输出当前对象(当虚部为非负数时,实部虚部中间用+号连接,当虚部为负数时,实部虚部用-号连接:如3+4i,3-4i,3+0i)。重载......
  • 关于Java中方法重载和方法重写
    方法重写是子类继承父类(默认继承Object类)后覆盖父类的方法需要保证同名同参同返回值且访问权限范围不能缩小(public>protected>default>private)publicclassFather{ publicintmethod(){ return-1; }}classSonextendsFather{ //访问范围不能小返回值方法......
  • 面积计算器(函数重载)
    一.问题描述:实现一个计算器,能够计算矩形或长方形的面积;二.编程思路:1.定义area函数2.定义主函数3.设立for循环4.设定if选择结构三.代码实现:#include<iostream>#include<string>usingnamespacestd;intarea(int,int);intarea(int,int,int);intmain(){inti,......
  • 4/18打卡 复数的输入输出和加减乘除重载
    classComplex{doublereal;doubleimag;public:friendistream&operator>>(istream&is,Complex&c);friendostream&operator<<(ostream&os,constComplex&a);Complex(){real=0;......