Java中的可变长参数可以这样表示:
String...args
而其与String s(即单参数)方法的多态性成了一个很有意思的问题。
package cn.xujin;
public class Regex2
{
public static void main(String args[])
{
Base a = new Child();
a.test("one");//Base
//a.test("22","123");//error,编译错误
Child b = (Child)a;
b.test("one");//Base
b.test("one","two");//Child
}
}
class Base{
public void test(String s){
System.out.println("Base");
}
}
class Child extends Base{
public void test(String...args){
System.out.println("Child");
}
}
运行上述程序可以知道:
a是一个Child类型,可是被Base引用,调用a.test("one")调用的是Base类中的;而a.test("one","two");不能编译,是因为Base类中无两个参数的test方法
b也是一个Child类型,被Child类型引用,b.test("one")调用的是Base类中的,而b.test("one","two");调用的是Child类中的变长参数方法。
Base类中只有一个单参数的方法,而Child类中有一个单参数的方法和一个变长参数的方法。当调用单参数方法时,发生冲突,此时虚拟机会不管变长参数方法,而直接调用完全匹配的那个方法。
我们看到,两个以上参数的情况符合函数重载(Overload);而单参数的情况并不符合重写(Override)的规则。可以说,这是一种很特殊的重载。
因而:
两个及以上参数的时候,按照重载(Overload)来;而单参数的情况下,调用a.test("one"),Base仅有单参数方法,所以必须调用Base中的test方法,输出“Base”。调用b.test("one"),Child有可变参数方法也有继承来的单参数方法,所以虚拟机会不管变长参数方法,而直接调用完全匹配的那个方法,输出“Base”。
我们再来看一种情况来验证上述观点:
package cn.xujin;
import java.util.regex.*;
public class Regex2
{
public static void main(String args[])
{
Base a = new Child();
a.test("one");//Base
a.test("one","two");//Base
Child b = (Child)a;
b.test("one","two");//Base
b.test("one");//Child
}
}
class Base{
public void test(String...args){
System.out.println("Base");
}
}
class Child extends Base{
public void test(String s){
System.out.println("Child");
}
}
与上面同理,Base类中只有一个可变参数的方法,而Child类中有一个单参数的方法和一个变长参数的方法。
单参数的情况下,调用a.test("one"),Base仅有可变参数方法,所以必须调用Base中的test方法,输出“Base”。调用b.test("one"),Child有可变参数方法也有继承来的单参数方法,所以虚拟机会不管变长参数方法,而直接调用完全匹配的那个方法,输出“Child”。
今天我又遇到这么一种情况,不是父类子类的关系:
package cn.xujin;
import java.util.regex.*;
public class A{
public String doit(int x, int y){
return "a";
}
public String doit(int...vals){
return "b";
}
public static void main(String...args){
A a = new A();
System.out.println(a.doit(3, 4));//a
}
}
这种情况下,虚拟机会先抛开可变长参数的方法,查找有没有能直接匹配的方法,如果找到再运行,否则去查找可变长参数的方法。