关闭

Java不定长参数

标签: javajava不定长参数不定长参数varargs
357人阅读 评论(1) 收藏 举报
分类:

在Java5中提供了不定长参数(varargs:variable number of arguments)、也就是在方法定义中可以使用个数不确定的参数、对于同一方法可以使用不同个数的参数调用、下面介绍如何定义不定长参数、以及如何使用不定长参数、


一、不定长参数的基本使用

定义实参个数可变的方法:只要在一个形参的类型与参数名之间加上三个连续的 “.”(即 “…”、英文里的句中省略号)、就可以让它和不确定个实参相匹配。

public class Main {

    /** 不定长参数方法 */
    static int sumvarargs(int... intArrays) {
        int sum = 0;
        for (int i = 0; i < intArrays.length; i++) {
            sum += intArrays[i];
        }
        return sum;
    }

    public static void main(String args[]) {
        // 调用方式一
        int sum1 = sumvarargs(10, 12, 13);

        // 调用方式二
        int[] varargs = new int[]{10, 12, 13};
        int sum2 = sumvarargs(varargs);

        System.out.printf("sum1:%d%n", sum1); // 输出结果 => sum1:35
        System.out.printf("sum2:%d%n", sum2); // 输出结果 => sum2:35
    }

}

工作原理:
1. 以调用方传递的参数的数目为长度创建一个数组、
2. 将实参的值放入数组中、
3. 将数组的引用传递给被调方法、

Java源码使用例子:String.format(String format, Object... args)


二、不定长参数问题和规范

1、调用问题和规范

  1. 如果调用的方法可以和两个可变参数匹配、则编译报错

    public class Main {
    
        static int sumvarargs(int... intArrays) {
            int sum = 0;
            for (int i = 0; i < intArrays.length; i++) {
                sum += intArrays[i];
            }
            return sum;
        }
    
        static int sumvarargs(int intArray, int... intArrays) {
            int sum = intArray;
            for (int i = 0; i < intArrays.length; i++) {
                sum += intArrays[i];
            }
            return sum;
        }
    
        public static void main(String args[]) {
            /*
             下面两个调用都不能编译通过、
             因为编译器不知道该选哪个方法调用
             */
            int sum1 = sumvarargs(10);
            int sum2 = sumvarargs(10, 12, 13);
    
            System.out.printf("sum:%d%n", sum1);
            System.out.printf("sum:%d%n", sum2);
        }
    
    }
  2. 如果调用可变长参数的重载方法时隐藏了实参类型、也可能发生类似问题一中错误、

    public class Main {
    
        static int sumvarargs(String desc, int... intArrays) {
            System.out.println(desc);
            int sum = 0;
            if (intArrays == null)
                return sum;
            for (int i = 0; i < intArrays.length; i++) {
                sum += intArrays[i];
            }
            return sum;
        }
    
        static int sumvarargs(String desc, String... strArrays) {
            System.out.println(desc);
            int sum = 0;
            if (strArrays == null)
                return sum;
            for (int i = 0; i < strArrays.length; i++) {
                int intArray = Integer.valueOf(strArrays[i]);
                sum += intArray;
            }
            return sum;
        }
    
        public static void main(String args[]) {
            /*
             下面两个调用都不能编译通过、
             因为编译器不知道该选哪个方法调用
             */
            int sum1 = sumvarargs("sum");
            int sum2 = sumvarargs("sum", null);
    
            System.out.printf("sum1:%d%n", sum1);
            System.out.printf("sum2:%d%n", sum2);
    
        }
    
    }   

    上面的情况是由于不是很好的编码习惯造成的、即调用者隐藏了实参类型、
    避免这种情况的代码写法如下:

    public class Main {
    
        static int sumvarargs(String desc, int... intArrays) {
            System.out.println(desc);
            int sum = 0;
            if (intArrays == null)
                return sum;
            for (int i = 0; i < intArrays.length; i++) {
                sum += intArrays[i];
            }
            return sum;
        }
    
        static int sumvarargs(String desc, String... strArrays) {
            System.out.println(desc);
            int sum = 0;
            if (strArrays == null)
                return sum;
            for (int i = 0; i < strArrays.length; i++) {
                int intArray = Integer.valueOf(strArrays[i]);
                sum += intArray;
            }
            return sum;
        }
    
        /**
          控制台输出:
          调用int不定长方法
          调用str不定长方法
          sum1:0
          sum2:3    
          */
        public static void main(String args[]) {
    
            int[] intArrays = null;
            int sum1 = sumvarargs("调用int不定长方法", intArrays);
            int sum2 = sumvarargs("调用str不定长方法", new String[]{"1", "2"});
    
            System.out.printf("sum1:%d%n", sum1);
            System.out.printf("sum2:%d%n", sum2);
    
        }
    
    }
  3. 调用的方法能够和固定参数的方法匹配、也能够与可变长参数的方法匹配、则选择固定参数的方法

    public class Main {
    
        static int sumvarargs(int intArray) {
            return intArray * 2;
        }
    
        static int sumvarargs(int... intArrays) {
            int sum = 0;
            for (int i = 0; i < intArrays.length; i++) {
                sum += intArrays[i];
            }
            return sum;
        }
    
        public static void main(String args[]) {
    
            int sum1 = sumvarargs(10);
            int sum2 = sumvarargs(10, 12, 13);
    
            System.out.printf("sum1:%d%n", sum1); // 输出结果 => sum1:20
            System.out.printf("sum2:%d%n", sum2); // 输出结果 => sum2:35
    
        }
    
    }

2、定义问题和规范

  1. 一个方法只能有一个可变长参数、并且这个可变长参数必须是该方法的最后一个参数

    public class Main {
    
        /** 编译报错 */
        static void test(String... strs, List list) {}
    
        /** 编译报错 */
        static void test(String... strs, List... lists) {}
    
    }
  2. 重写变长方法也要循规蹈矩

    public class Main {
    
        public static void main(String[] args) {
            // 向上转型
            Base base = new Sub();
            base.print("hello");
    
            // 不转型
            Sub sub = new Sub();
            sub.print("hello"); // 此行编译不通过
        }
    
    }
    
    // 基类
    class Base {
    
        void print(String... args) {
            System.out.println("Base - args[0]:" + args[0]);
        }
    
    }
    
    // 子类,覆写父类方法
    class Sub extends Base {
    
        @Override
        void print(String[] args) {
            System.out.println("Sub - args[0]:" + args[0]);
        }
    
    }

    第一个能编译通过、这是为什么呢?事实上、Base对象把子类对象Sub做了向上转型、形参列表是由父类决定的、当然能通过、而看看子类直接调用的情况、这时编译器看到子类覆写了父类的print方法、因此肯定使用子类重新定义的print方法、尽管参数列表不匹配也不会跑到父类再去匹配下、因为找到了就不再找了、因此有了类型不匹配的错误、

    这是个特例、覆写的方法参数列表竟然可以与父类不相同、这违背了覆写的定义、并且会引发莫名其妙的错误、

    总结下覆写必须满足的条件:

    1. 重写方法不能缩小访问权限
    2. 参数列表必须与被重写方法相同(包括显示形式)
    3. 返回类型必须与被重写方法的相同或是其子类
    4. 重写方法不能抛出新的异常、或者超过了父类范围的异常、但是可以抛出更少、更有限的异常、或者不抛出异常

参考资料:Java中可变长参数的使用及注意事项

1
0
查看评论

java中在方法中定义不定长参数示例

public int getSum(int ...a){ for(int i=0;i
  • chongtian_zhiying
  • chongtian_zhiying
  • 2014-10-04 12:04
  • 2055

JAVA之函数重载不定长参数

可变的参数类型,也称为不定参数类型。只需要声明方法时,用上三点...即可。通过它的名字可以很直接地看出来,这个方法在接收参数的时候,个数是不定的。 public class TestVarArgus { public static void dealArray(int... intAr...
  • m631521383
  • m631521383
  • 2013-08-09 12:44
  • 1055

Java的不定长参数和Python的不定长参数对比

一:起因 (0)不定长参数,也叫可变的参数,就是再调用函数之前,并不确定到底需要传递多少个参数 (1)Java中的不定长参数用String... args / int... args等三个点来表示;Python中用*args元组来表示 / **args字典(map)来表示  (2)不...
  • u010700335
  • u010700335
  • 2015-05-19 17:01
  • 1594

java中不定长参数方法与定长参数方法的重载

在一个类中定义(重载)两个方法名、返回值一样,而一个方法中传入不定长参数,另一个传入的是定长参数。当在main中调用该方法,并且传入参数满足两个方法时,会使用的是哪一个方法呢? public class OverLoad{ public static void add(int...a){ S...
  • Veson__
  • Veson__
  • 2015-12-03 15:59
  • 955

不定长参数函数的实现

源码如下: int sum(int num, ...) { int *p = &num + 1; int ret = 0; while(num--) {    printf("%d\n", num);    ret ...
  • Blaider
  • Blaider
  • 2012-05-17 22:53
  • 4262

Python的不定长参数研究

以一个*开始的参数,代表一个任意长的元组: >>> def mul(*arg):...     print arg... >>> mul(1,2,3,4,5,6,7,'hello','pan...
  • longzhiwen888
  • longzhiwen888
  • 2015-06-19 16:19
  • 1358

java不定长参数

先看两个简单的例子,来感受一下Java的不定长度参数  第一个例子:  Java代码   public class VariArgs {       ...
  • zs064811
  • zs064811
  • 2016-03-04 10:12
  • 164

Python的不定参数

以一个*开始的参数,代表一个任意长的元组:>>> def mul(*arg):...     print arg... >>> mul(1,2,3,4,5,6,7,'hello','panf...
  • cnweike
  • cnweike
  • 2011-02-11 12:22
  • 7246

Java 不定长参数用法

Note:不定长参数一定要放在形参的最后一个,类型相同。   Demo 清单: public class Test { /** * Note strs must be the last parameter * @param strs */ public static vo...
  • zhangju1122
  • zhangju1122
  • 2013-06-14 10:23
  • 637

不定长参数——javascript

http://zhangh1014.blog.163.com/blog/static/177723473200711652940405/ 在javascript中,通过arguments对象可以获取function接收的参数,对于参数不固定的function是个不错的选择。 如: functi...
  • jji8877032
  • jji8877032
  • 2014-06-09 18:43
  • 446
    个人资料
    • 访问:6095次
    • 积分:165
    • 等级:
    • 排名:千里之外
    • 原创:9篇
    • 转载:4篇
    • 译文:0篇
    • 评论:3条
    最新评论