Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java方法参数:var args vs array_Java_Arrays_Guava_Variadic Functions - Fatal编程技术网

Java方法参数:var args vs array

Java方法参数:var args vs array,java,arrays,guava,variadic-functions,Java,Arrays,Guava,Variadic Functions,在整个Google Guava库中,我注意到使用“一(或两)加var args”技术的趋势 示例: void add(T值,T…moreValueArr) void add(T值,T值2,T…moreValueArr) 我花了一段时间才弄明白原因:防止调用零个参数(在第一种情况下)或一个参数(在第二种情况下) 进一步扩展此技术,如果在下面的场景A和场景B之间进行选择,哪一个更可取?我希望对Java有深入了解的人能够提供见解 情景A:(两种方法) void add(T…valueArr) vo

在整个Google Guava库中,我注意到使用“一(或两)加var args”技术的趋势

示例:

  • void add(T值,T…moreValueArr)
  • void add(T值,T值2,T…moreValueArr)
我花了一段时间才弄明白原因:防止调用零个参数(在第一种情况下)或一个参数(在第二种情况下)

进一步扩展此技术,如果在下面的场景A和场景B之间进行选择,哪一个更可取?我希望对Java有深入了解的人能够提供见解

情景A:(两种方法)

  • void add(T…valueArr)

  • voidadd(Iterable我会选择b的一个稍微修改的版本:

    void add (T first, T ... more){
       // call the second version
       add(Lists.asList(first, more);
    }
    void add(Iterable<? extends T> data){
       ... // do stuff here
    }
    

    尽管我怀疑它是否会比仅仅使用list.asList更有效,但我会选择一个,并鼓励用户(在方法文档中)将数组传递给您的方法,而不是varargs,因为每次调用varargs方法时都必须创建一个数组,如前所述

    此外,您还可以通过使用a改进
    add(Iterable data)
    方法,并将其签名更改为
    add(Iterable),最后将得出结论。如果您只想得到结论,请跳到结尾


    主要目标是绩效。

    如果有很多用例中只有1或2个元素会被传递,那么您可以避免创建数组。是的,仍然会传递一个零长度数组,但是由于不能修改零长度数组,因此允许JVM传递一个共享实例,例如,如果缓存了该实例,则根本不会影响性能

    最突出的例子是
    EnumSet.of()
    方法(它返回所列枚举实例的
    EnumSet

    您将看到以下重载:

    static <E extends Enum<E>> EnumSet<E> of(E e);
    static <E extends Enum<E>> EnumSet<E> of(E first, E... rest);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5);
    
    静态枚举集(E);
    静态枚举集(E-first,E…rest);
    (e1,e2)的静态枚举集;
    (e1,e2,e3)的静态枚举集;
    (e1,e2,e3,e4)的静态枚举集;
    (e1、e2、e3、e4、e5)的静态枚举集;
    
    如果使用5个或更少的元素调用
    of()
    方法,将不会创建数组,因为存在可以使用5个或更少元素的重载

    此工厂的参数列表使用varargs功能,可能是 用于创建初始包含任意数量枚举的枚举集 元素,但它的运行速度可能比重载慢 不要使用varargs

    关于为什么要使用(E优先,E…rest)的
    ,即使有单独的
    的(E e1,E e2)

    这只是为了方便实现。如果首先声明
    参数,则可以使用它,而不必检查数组的长度或使用索引。例如,可以使用来检查其类型(这在处理泛型时通常很重要)

    它实际上并不强制至少传递一个参数,因为如果只有vararg参数,那么传递
    null
    就像传递空数组一样容易

    Vararg与数组的比较

    如果数组的类型不是基元类型,则没有真正的区别,除了数组参数强制您显式创建数组,而vararg参数允许您传递数组或仅列出元素

    尽管有使用数组参数的历史原因(varargs仅在5.0中加入Java),但仍有需要使用数组的地方:

  • 如果数组参数是“传出”参数,则表示接收数组的方法将快速填充数组。示例:
  • 如果有其他参数,可能是多个数组,显然vararg是不够的,因为只能有一个vararg参数(也必须在末尾)
  • Iterable参数

    Iterable
    在这种情况下是将多个值传递给方法的替代方法,但它不是数组和vararg参数的替换。
    Iterable
    用于集合,因为如果参数是
    Iterable
    (数组不实现
    Iterable
    ),则不能使用数组或列出元素。如果调用者以集合的形式拥有输入数据(例如
    列表
    集合
    ),则
    Iterable
    参数是传递元素最方便、最通用和最有效的方法


    得出结论

    回到原始场景A和B。由于两个场景都包含带有
    Iterable
    参数的方法,并且
    Iterable
    s不与数组“混合”,因此我通过省略这些选项来减少问题:

    情景A:(一种方法)

  • void add(T…valueArr)
  • 情景B:(两种方法)

  • void add(T值,T…moreValueArr)
  • void add(T[]valueArr)

  • 因为方法
    add()
    只从数组中读取数据(而不是向数组中写入数据;根据名称
    add
    假设),每一个用例都可以用它们来解决。为了简单起见,我会选择场景A

    没有特别的原因,您提供的A和B选项是相互排斥的,也不是唯一可用的选项。相反,请认识到varargs解决的问题与集合不同

    Guava(和现代Java最佳实践)极力鼓励使用集合而不是数组。它们比数组更具可扩展性和可互换性,并提供更强大的抽象,如惰性迭代

    另一方面,varargs提供了一种很好的方法来调用方法。如果您希望人们希望直接传入参数,而不是作为集合的一部分,那么varargs更方便。几乎所有varargs样式的方法都应该只调用
    YourType[] arr3 = new YourType[3]; //declared as field
    ...
    arr3[0] = a;
    arr3[1] = b;
    arr3[2] = c;
    add(arr3);
    
    static <E extends Enum<E>> EnumSet<E> of(E e);
    static <E extends Enum<E>> EnumSet<E> of(E first, E... rest);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4);
    static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5);
    
    void a(int[] args) { }
    void b(int ... args) { }
    
    a(1, 2, 3);
    
    b(new int[] { 1, 2, 3 });
    
    a(int[] args, int arg);
    a(int ... args, int arg); // Won't even compile.
    
    c(int arg, int ... args) { }