区别不同函数的唯一标志是参数列表,重载的函数,它们的函数名相同,返回类型可以相同也可以不同,但它们的参数列表一定不能相同。与继承中的方法重写不同,重写的方法要求函数名和参数列表一定相同。
There are three factors that make overloading a little tricky:
(1) Widening
(2) Boxing
(3) Var-args
1. 自动提升时的规则
class EasyOver {static void go(short x) { System.out.print("short "); }static void go(int x) { System.out.print("int "); }static void go(long x) { System.out.print("long "); }static void go(double x) { System.out.print("double "); }public static void main(String [] args) {char c = 'a';byte b = 5; short s = 5;long l = 5;float f = 5.0f;go(c); //go(int)go(b); //go(short)go(s); //go(short)go(l); //go(long)go(f); //go(double)}
}
Which produces the output:
This probably isn't much of a surprise.
In every case, when an exact match isn't found, the JVM uses the method with the smallest argument that is wider than the parameter.
char produces a slightly different effect, since if it do not find an exactchar match,it is promoted to int. char can not be promotedbyte and short whenever it is, it can be promotedlong,float and double if int does not exist.
2. Overloading with Boxing and Var-args
(1) overloading with boxing
class AddBoxing {static void go(Integer x) { System.out.println("Integer"); }static void go(long x) { System.out.println("long"); }public static void main(String [] args) {int i = 5;go(i); // which go() will be invoked?}
}
Does the compiler think that widening a primitive parameter is more desirable than performing an autoboxing operation? The answer is that the compiler willchoose widening over boxing, so the output will be:
(2) overloading with var-args
class AddVarargs {static void go(long x, long y) { System.out.println("long,long");}static void x) { System.out.println( "); } public static void main(String[] args) {byte b = 5;go(b,b); // which go() will be invoked?}
}
So far, we have seen that
(*) Wideningbeats boxing
(**) Widening beats var-args
At this point, inquiring minds want to know, does boxing beat var-args?
(3) Box or Var-args
class BoxOrVararg {static void go(Byte x, Byte y) { System.out.println("Byte, Byte"); }static void x) { System.out.println( "); } public static void main(String [] args) {byte b = 5;go(b,b); // which go() will be invoked?}
}
So we have seen another rule:
(*) boxing beats var-args
And var-args is the last choice to select.
3. Overloading When Combining Widening and Boxing
In this case the compiler will have to widen and then autobox the parameter for a match to be made:
class WidenAndBox {static void go(Long x) { System.out.println("Long"); }public static void main(String [] args) {byte b = 5;go(b); //widen then box, it is illegal }
}
Widen then box, it is illegal.
Strangely enough, it IS possible for the compiler to perform a boxing operation followed by a widening operation in order to match an invocation to a method.
class BoxAndWiden {static void go(Object o) {Byte b2 = (Byte) o; // ok - it's a Byte objectSystem.out.println(b2);}public static void main(String [] args) {byte b = 5;go(b); // can this byte turn into an Object ? }
}
It should box then widen.
Wow! Here's what happened under the covers when the compiler, then the JVM, got to the line that invokes the go() method:
1) The byte b was boxed to a Byte.
2) The Byte reference was widened to an Object (since Byte extends Object).
3) The go() method got an Object reference that actually refers to a Byte object.
4) The go() method cast the Object reference back to a Byte reference (remember, there was never an object of type Object in this scenario, only anobject of type Byte!).
5) The go() method printed the Byte's value.
4. Overloading in Combination with Var-args
What happens when we attempt to combine var-args with either widening or boxing in a method-matching scenario? Let's take a look:
class Vararg {static void wide_ x) { System.out.println("); }static void box_ x) { System.out.println("); }public static void main(String [] args) {int i = 5;wide_vararg(i,i); // needs to widen and use var-argsbox_vararg(i,i); // needs to box and use var-args}
}
As we can see, you can successfully combine var-args with either widening or boxing.
So the following codes wil be failed.
class Ambiguous {static void x) { System.out.println("); }static void x) { System.out.println("); }public static void main(String [] args) {int i = 5;vararg(i,i); // widen first or box first and before using var-arg? Both yes!}
}
Another example:
public class Ambiguous2 {public static void test(float a, c) {System.out.println("float, ");}public static void c) {System.out.println(");}public static void main(String[] args) {test('a', 'b'); // widen first or box first before using var-arg ?}
}
5. review of the rules for overloading methods using widening, boxing, and var-args
(1) Primitive widening uses the "smallest" method argument possible.
(2) Used individually, boxing and var-args are compatible with overloading.
(3) You CANNOT widen from one wrapper type to another. (IS-A fails.)
(4) You can box and then widen. (An int can become an Object, via Integer.)
(4) You can combine var-args with either widening or boxing.
本文发布于:2024-01-28 23:33:34,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170645602111098.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |