­

Java基础:五、方法重载(2)

  • 2020 年 3 月 17 日
  • 筆記

方法重载

在Java里,构造器是强制重载方法名的另一个原因。既然构造器的名字已经由类名所决定,就只能有一个构造器名,如果想用多种方式创建一个对象该怎么办呢?这就需要两个构造器:一个默认构造器,另一个带有形式参数,由于都是构造器,所以它们必须有相同的名字,即类名。为了让方法名相同而形式参数不同的构造器同时存在,必须用到方法重载。同时,尽管方法重载是构造器所必需的,但也可应用于其他方法,且用法同样方便。

class Tree{      int height;      Tree(){          System.out.println("Planting a seeding");          height = 0;      }        Tree(int initialHeight){          height = initialHeight;          System.out.println("Creating new Tree that is " + height + " feel tall");      }        void info(){          System.out.println("Tree is " + height+ " feet tall");      }        void info(String s){          System.out.println(s + ": Tree is " + height + " feet tall");      }        public static void main(String[] args) {          for(int i = 0; i < 3; i++){              Tree t = new Tree(i);              t.info();              t.info("overloaded method");          }          new Tree();      }  }  // Output  Creating new Tree that is 0 feel tall  Tree is 0 feet tall  overloaded method: Tree is 0 feet tall  Creating new Tree that is 1 feel tall  Tree is 1 feet tall  overloaded method: Tree is 1 feet tall  Creating new Tree that is 2 feel tall  Tree is 2 feet tall  overloaded method: Tree is 2 feet tall  Planting a seeding

区分重载方法

要是几个方法有相同的方法,Java如何才能知道你指的是哪一个呢?其实规则很简单:每个重载的方法都必须有一个独一无二的参数类型列表,对于名字相同的方法,除了参数类型的差异以外,甚至参数顺序的不同也足以区分两个方法(不过,一般情况下别这么做,因为这会使代码难以维护)

// 区分重载方法  class OverLoadingOrder{      static void f(String s,int i){          System.out.println("String: " + s + ", int: " + i);      }      static void f(int i, String s){          System.out.println("int: " + i + ", String: " + s);      }      public static void main(String[] args) {          f("String first",11);          f(99,"Int first");      }  }

基本类型的重载

class PrimitiveOverloading{        void f1(char x){          System.out.print("f1(char)");      }      void f1(byte x){          System.out.print("f1(byte)");      }      void f1(short x){          System.out.print("f1(short)");      }      void f1(int x){          System.out.print("f1(int)");      }      void f1(long x){          System.out.print("f1(long)");      }      void f1(float x){          System.out.print("f1(float)");      }      void f1(double x){          System.out.print("f1(double)");      }        void f2(byte x){          System.out.print("f2(byte)");      }      void f2(short x){          System.out.print("f2(short)");      }      void f2(int x){          System.out.print("f2(int)");      }      void f2(long x){          System.out.print("f2(long)");      }      void f2(float x){          System.out.print("f2(float)");      }      void f2(double x){          System.out.print("f2(double)");      }          void f3(short x){          System.out.print("f3(short)");      }      void f3(int x){          System.out.print("f3(int)");      }      void f3(long x){          System.out.print("f3(long)");      }      void f3(float x){          System.out.print("f3(float)");      }      void f3(double x){          System.out.print("f3(double)");      }        void f4(int x){          System.out.print("f4(int)");      }      void f4(long x){          System.out.print("f4(long)");      }      void f4(float x){          System.out.print("f4(float)");      }      void f4(double x){          System.out.print("f4(double)");      }        void f5(long x){          System.out.print("f5(long)");      }      void f5(float x){          System.out.print("f5(float)");      }      void f5(double x){          System.out.print("f5(double)");      }        void f6(float x){          System.out.print("f6(float)");      }      void f6(double x){          System.out.print("f6(double)");      }        void f7(double x){          System.out.print("f7(double)");      }        void testConstVal(){          System.out.print("5: ");          f1(5);f2(5);f3(5);  f4(5);f5(5); f6(5); f7(5);      }        void testChar(){          char x = 'x';          System.out.print("char:");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testByte(){          byte x = 0;          System.out.print("byte: ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testShort(){          short x = 0;          System.out.print("short : ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testInt(){          int x = 0;          System.out.print("int : ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testLong(){          long x = 0;          System.out.print("long: ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testFloat(){          float x = 0;          System.out.print("float: ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        void testDouble(){          double x = 0;          System.out.print("double: ");          f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);      }        public static void main(String[] args) {          PrimitiveOverloading p = new PrimitiveOverloading();          p.testConstVal();          System.out.println();          p.testChar();          System.out.println();          p.testByte();          System.out.println();          p.testShort();          System.out.println();          p.testInt();          System.out.println();          p.testLong();          System.out.println();          p.testFloat();          System.out.println();          p.testDouble();      }  }  // Output  5: f1(int)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)  char:f1(char)f2(int)f3(int)f4(int)f5(long)f6(float)f7(double)  byte: f1(byte)f2(byte)f3(short)f4(int)f5(long)f6(float)f7(double)  short : f1(short)f2(short)f3(short)f4(int)f5(long)f6(float)f7(double)  int : f1(int)f2(int)f3(int)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)

数值5被当作int值处理,所以如果有某个重载方法接收int型参数,它就会被调用。如果传入的数据类型(实际参数类型)小于声明中的形式参数类型,实际数据类型就会被提升。char型不同,如果无法找找恰好接受char参数的方法,就会把char直接提升至int型

如果传入的实际参数大于重载方法声明的形式参数,方法接受较小的基本类型作为参数,如果传入的实际参数较大,就得通过类型转换来执行窄化转换。如果不这样做,编译器就会报错

// 基本类型的重载,窄化处理  class Demotion{        void f1(char x){          System.out.print("f1(char)");      }      void f1(byte x){          System.out.print("f1(byte)");      }      void f1(short x){          System.out.print("f1(short)");      }      void f1(int x){          System.out.print("f1(int)");      }      void f1(long x){          System.out.print("f1(long)");      }      void f1(float x){          System.out.print("f1(float)");      }      void f1(double x){          System.out.print("f1(double)");      }        void f2(byte x){          System.out.print("f2(byte)");      }      void f2(short x){          System.out.print("f2(short)");      }      void f2(int x){          System.out.print("f2(int)");      }      void f2(long x){          System.out.print("f2(long)");      }      void f2(float x){          System.out.print("f2(float)");      }      void f2(double x){          System.out.print("f2(double)");      }        void f3(short x){          System.out.print("f3(short)");      }      void f3(int x){          System.out.print("f3(int)");      }      void f3(long x){          System.out.print("f3(long)");      }      void f3(float x){          System.out.print("f3(float)");      }      void f3(double x){          System.out.print("f3(double)");      }        void f4(int x){          System.out.print("f4(int)");      }      void f4(long x){          System.out.print("f4(long)");      }      void f4(float x){          System.out.print("f4(float)");      }      void f4(double x){          System.out.print("f4(double)");      }        void f5(long x){          System.out.print("f5(long)");      }      void f5(float x){          System.out.print("f5(float)");      }      void f5(double x){          System.out.print("f5(double)");      }        void f6(float x){          System.out.print("f6(float)");      }      void f6(double x){          System.out.print("f6(double)");      }        void f7(double x){          System.out.print("f7(double)");      }          void testDouble(){          double x = 0;          System.out.print("double argument: ");          f1(x);f2((float)x);f3((long)x);f4((int)x);f5((short)x);f6((byte)x);f7((char)x);      }        public static void main(String[] args) {          Demotion p = new Demotion();          p.testDouble();      }  }  // Output  double argument: f1(double)f2(float)f3(long)f4(int)f5(long)f6(float)f7(double)

以返回值区分重载方法

如果两个方法拥有相同的类名和参数列表,如果考虑用方法的返回值来区分呢?比如现有有两个方法void f(){}int f(){return1} 只要编译器可以根据语境明确判断出语义,比如在int x = f()中,那么的确可以据此区分重载方法。不过,有时你并不关心刚发的返回值,你想要的是方法调用的其他效果(这常被称为“为了副作用而调用”),这时你可能会调用方法而忽略其返回值。如果像这样调用方法f();,此时Java如何才能判断该调用哪一个f()呢?别人该如何理解这种代码呢?因此,根据方法的返回值来区分重载方法是行不通的