• 方法重载,为什么不能根据返回类型来区分?


    详见:四

    一、方法重载简述

    任何程序设计语言都具备一项重要特性就是对名字的运用。当创建一个对象时,也就给此对象分配到的存储空间取一个名字。

    所谓方法,则是给某个动作取的名字。通过这个名字,你可以引用所有的对象和方法。名字起的好可以使系统更易于理解和修改。

    在日常生活中,相同的词可以表达多种不同的含义——它们被“重载”了。特别是含义之间的差别很小时,这种方式十分有用。比起“以洗衬衫的方式洗衬衫”、“以洗狗的方式洗狗”、“以洗车的方式洗车”,“洗洗衬衫”、“洗洗狗”、“洗洗车”显得更加简洁和方便。

       wash(Shirt shirt); wash(Dog dog); wash(Car car);

    大多数程序设计语言(尤其是C)要求为每个方法都提供一个独一无二的标识符。所以绝不能用名为print()的函数显示一个整数之后,有用print()显示浮点数。即不支持重载,每个函数都要有唯一的名称。

    Java和C++支持重载(例如:构造方法重载,通过不同的构造方法,用多种方式创建一个对象)。

    二、区分重载方法

    规则很简单:每个重载方法都必须有一个独一无二的参数类型列表

      1、参数个数

      2、参数类型

      3、参数顺序(一般不用,容易造成维护困难)

    三、涉及基本类型的重载

    1、当实参类型小于形参类型,实际数据类型就会被提升。

      注意:char类型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。

    示例代码:

      1 package com.mianshi.easy;
      2 
      3 public class Overload {
      4     
      5     void f1(char x){System.out.print("f1(char)"+"、");};
      6     void f1(byte x){System.out.print("f1(byte)"+"、");};
      7     void f1(int x){System.out.print("f1(int)"+"、");};
      8     void f1(long x){System.out.print("f1(long)"+"、");};
      9     void f1(float x){System.out.print("f1(float)"+"、");};
     10     void f1(short x){System.out.print("f1(short)"+"、");};
     11     void f1(double x){System.out.print("f1(double)"+"、");};
     12     
     13     void f2(byte x){System.out.print("f2(byte)"+"、");};
     14     void f2(int x){System.out.print("f2(int)"+"、");};
     15     void f2(long x){System.out.print("f2(long)"+"、");};
     16     void f2(float x){System.out.print("f2(float)"+"、");};
     17     void f2(short x){System.out.print("f2(short)"+"、");};
     18     void f2(double x){System.out.print("f2(double)"+"、");};
     19     
     20     void f3(int x){System.out.print("f3(int)"+"、");};
     21     void f3(long x){System.out.print("f3(long)"+"、");};
     22     void f3(float x){System.out.print("f3(float)"+"、");};
     23     void f3(short x){System.out.print("f3(short)"+"、");};
     24     void f3(double x){System.out.print("f3(double)"+"、");};
     25     
     26     void f4(int x){System.out.print("f4(int)"+"、");};
     27     void f4(long x){System.out.print("f4(long)"+"、");};
     28     void f4(float x){System.out.print("f4(float)"+"、");};
     29     void f4(double x){System.out.print("f4(double)"+"、");};
     30     
     31     void f5(long x){System.out.print("f5(long)"+"、");};
     32     void f5(float x){System.out.print("f5(float)"+"、");};
     33     void f5(double x){System.out.print("f5(double)"+"、");};
     34     
     35     void f6(float x){System.out.print("f6(float)"+"、");};
     36     void f6(double x){System.out.print("f6(double)"+"、");};
     37     
     38     void f7(double x){System.out.print("f7(double)"+"、");};
     39     
     40     void testConstVal(){
     41         System.out.print("5:"+"      ");
     42         f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);
     43     }
     44     
     45     void testChar(){
     46         char x = 'x';
     47         System.out.print("char:"+"   ");
     48         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     49     }
     50     
     51     void testByte(){
     52         byte x = 0;
     53         System.out.print("byte:"+"   ");
     54         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     55     }
     56     
     57     void testShort(){
     58         byte x = 0;
     59         System.out.print("short:"+"  ");
     60         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     61     }
     62     
     63     void testInt(){
     64         int x = 0;
     65         System.out.print("int:"+"    ");
     66         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     67     }
     68     void testLong(){
     69         long x = 0;
     70         System.out.print("long:"+"   ");
     71         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     72     }
     73     
     74     void testFloat(){
     75         float x = 0;
     76         System.out.print("float:"+"  ");
     77         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     78     }
     79     
     80     void testDouble(){
     81         double x = 0;
     82         System.out.print("double:"+" ");
     83         f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);
     84     }
     85     
     86     public static void main(String[] args) {
     87         
     88         Overload o = new Overload();
     89         
     90         //按顺序一一解注释下面代码,观察结果
     91         o.testChar();
     92         /*o.testByte();
     93         o.testConstVal();
     94         o.testInt();
     95         o.testShort();
     96         o.testLong();
     97         o.testFloat();
     98         o.testDouble();*/
     99     }
    100 }
    View Code

    结果:

    char:   f1(char)、f2(int)、f3(int)、f4(int)、f5(long)、f6(float)、f7(double)、

    当传入参数为char类型时,f1中有接受char型参数的方法,直接调用,f2-f4中没有接受char型参数的方法,将直接提升为int型,然后f5-f7中逐步提升。

    注释第一条,解注释第二条:

    结果:

    byte:   f1(byte)、f2(byte)、f3(short)、f4(int)、f5(long)、f6(float)、f7(double)、

    f1、f2中有接受byte型参数的方法,直接调用,f3-f7中没有接受byte型参数的方法,将逐步提升。

    注释前两条,解注释第三条:

    结果:

    5:      f1(int)、f2(int)、f3(int)、f4(int)、f5(long)、f6(float)、f7(double)、

    常量值 5 被当做int型值进行处理,所以如果某个重载方法接受int型参数,它就会被调用,f1-f4中接受int型数据,之后逐步提升。

    注释前三条,解注释第四条:

    结果:

    int:    f1(int)、f2(int)、f3(int)、f4(int)、f5(long)、f6(float)、f7(double)、

    同上。

    注释前四条,解注释第五条:

    结果:

    short:  f1(short)、f2(short)、f3(short)、f4(int)、f5(long)、f6(float)、f7(double)、

    注释前五条,解注释第六条:

    结果:

    long:   f1(long)、f2(long)、f3(long)、f4(long)、f5(long)、f6(float)、f7(double)、

    注释前六条,解注释第七条:

    结果:

    float:  f1(float)、f2(float)、f3(float)、f4(float)、f5(float)、f6(float)、f7(double)、

    注释前七条,解注释第八条:

    结果:

    double: f1(double)、f2(double)、f3(double)、f4(double)、f5(double)、f6(double)、f7(double)、

    2、当实参类型大于形参类型,必须强制转换。

     1 package com.mianshi.easy;
     2 
     3 public class Overload {
     4     
     5     void f1(char x){System.out.print("f1(char)"+"、");};
     6     void f1(byte x){System.out.print("f1(byte)"+"、");};
     7     void f1(short x){System.out.print("f1(short)"+"、");};
     8     void f1(int x){System.out.print("f1(int)"+"、");};
     9     void f1(long x){System.out.print("f1(long)"+"、");};
    10     void f1(float x){System.out.print("f1(float)"+"、");};
    11     void f1(double x){System.out.print("f1(double)"+"、");};
    12     
    13     void f2(byte x){System.out.print("f2(byte)"+"、");};
    14     void f2(int x){System.out.print("f2(int)"+"、");};
    15     void f2(long x){System.out.print("f2(long)"+"、");};
    16     void f2(float x){System.out.print("f2(float)"+"、");};
    17     void f2(short x){System.out.print("f2(short)"+"、");};
    18     void f2(char x){System.out.print("f2(char)"+"、");};
    19     
    20     void f3(int x){System.out.print("f3(int)"+"、");};
    21     void f3(long x){System.out.print("f3(long)"+"、");};
    22     void f3(byte x){System.out.print("f3(byte)"+"、");};
    23     void f3(short x){System.out.print("f3(short)"+"、");};
    24     void f3(char x){System.out.print("f3(char)"+"、");};
    25     
    26     void f4(int x){System.out.print("f4(int)"+"、");};
    27     void f4(short x){System.out.print("f4(short)"+"、");};
    28     void f4(byte x){System.out.print("f4(byte)"+"、");};
    29     void f4(char x){System.out.print("f4(char)"+"、");};
    30     
    31     void f5(short x){System.out.print("f5(short)"+"、");};
    32     void f5(byte x){System.out.print("f5(byte)"+"、");};
    33     void f5(char x){System.out.print("f5(char)"+"、");};
    34     
    35     void f6(byte x){System.out.print("f6(byte)"+"、");};
    36     void f6(char x){System.out.print("f6(char)"+"、");};
    37     
    38     void f7(char x){System.out.print("f7(char)"+"、");};
    39     
    40     void testDouble(){
    41         double x = 0;
    42         System.out.print("double:"+" ");
    43         f1(x);f2((float)x);f3((long)x);f4((int)x);f5((short)x);f6((byte)x);f7((char)x);
    44     }
    45     
    46     public static void main(String[] args) {
    47         
    48         Overload o = new Overload();
    49         
    50         o.testDouble();
    51     }
    52 }
    View Code

    结果:

    double: f1(double)、f2(float)、f3(long)、f4(int)、f5(short)、f6(byte)、f7(char)、

    通过这种转换来执行窄化转换,否则编译器会出错。

    四、以返回值区分重载方法

      如下两个方法:

        void f(){}

        int f(){ return 1;}

    只要编译器可以根据语境明确判断出语义,比如在int x = f();中,那么的确可以据此区分重载方法。不过,有时你并不关心方法的返回值,你想要的是方法调用的其他效果(这常被称为“为了副作用而调用”),这时你可能会调用方法而忽略其返回值,所以如果像下面的调用:

        fun();

    此时Java如何才能判断调用的是哪一个 f() 呢?别人如何理解这种代码呢?所以,根据方法返回值来区分重载方法是行不通的。

    以上参考《Java 编程思想》 

    五、网上看到的两个小例子,熟悉一下:(转自:http://www.knowsky.com/369172.html)

     1 package com.mianshi.easy;
     2 
     3 public class TestOverLoad
     4 {
     5     public static void main(String[] args)
     6     {
     7         Test test = new Test();
     8         test.print(null);  
     9     } 
    10 }
    11 
    12 class Test
    13 {
    14     //定义一个方法print()
    15     public void print(String some)
    16     {
    17         System.out.println("String version print");
    18     } 
    19     //重载print()方法
    20     public void print(Object some)
    21     {
    22         System.out.println("Object version print"); 
    23     }
    24 }
    View Code

    结果:

    String version print

    这个题目明显是考察方法重载的,重载使得java的类可以有具有多个相同方法名的方法。编译器可以通过方法的参数的类型和个数来区分他们。而返回值和异常是不能作为区别标志的。上面的程序输出了String version print是遵循了方法重载中准确性的原则,null是作为一个很非凡的参数传给了方法print(),因为你可以认为null是String,也可以认为null是Object。但是从层次上看Object处在更上层,String是从Object继续过来的,调用print(String some)将更准确。

      假如在TestOverLoad类中再添加一个方法如下所示,这样会如何呢?

     1 package com.mianshi.easy;
     2 
     3 public class TestOverLoad
     4 {
     5     public static void main(String[] args)
     6     {
     7         Test test = new Test();
     8         test.print(null);  
     9     } 
    10 }
    11 
    12 class Test
    13 {
    14     //定义一个方法print()
    15     public void print(String some)
    16     {
    17         System.out.println("String version print");
    18     } 
    19     //重载print()方法
    20     public void print(Object some)
    21     {
    22         System.out.println("Object version print"); 
    23     }
    24     //重载print()方法
    25     public void print(StringBuffer some)
    26      {
    27       System.out.println("StringBuffer version print"); 
    28      }
    29 }
    View Code

    结果:

    Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
        The method print(String) is ambiguous for the type Test
    
        at com.mianshi.easy.TestOverLoad.main(TestOverLoad.java:8)

    答案是不能通过编译,为什么呢?

    由于StringBuffer和String并没有继续上的关系,因此编译器感觉StringBuffer和String作为参数的方法都很准确,它就不知道到时候会运行哪个方法了,因此会出现编译错误,这是方法重载中唯一性的原则。假如我们把参数null修改为"hello world",那么就可以通过编译并运行输出String version print了。

  • 相关阅读:
    Linux共享对象之编译参数fPIC
    如果重新设计网络,有没有可能合并IP地址跟MAC地址?
    HTTP的长连接和短连接
    Icon资源详解[2]
    Icon资源详解[1]
    LZMA demo挑选使用备忘
    SSM 拦截器验证权限和登录与注销的实现
    Intellij idea workflow 工作流插件安装
    C# HttpWebRequest post 请求传参数
    PLSQL 11注册码
  • 原文地址:https://www.cnblogs.com/gongxing/p/4670817.html
Copyright © 2020-2023  润新知