【问题标题】:Varargs in a group?Varargs 在一个组中?
【发布时间】:2013-04-05 20:55:18
【问题描述】:

关于Varargs,我可以在一组中重复参数吗?

例如,我想允许用户传入:

myFunc(1, "one");
myFunc(1, "one", 2, "two");
myFunc(1, "one", 2, "two", 3, "three");

这似乎是不可能的。但正如docs 中提到的,可变参数实际上是一个数组,在旧的实现中。我想知道 人们是如何 发明可变参数的。这可能会启发我们如何实现上述场景。我们可以将我的场景视为{int, String}...毕竟在重复。

感谢您的任何意见 :-)

编辑:

感谢您的所有投入!

那么,myFunc(new wrap(1, "one"), new wrap(2, "two"), new wrap(3, "three"));调用是不是方法?

编辑 2:

嗯,不。那是我混乱的错。

对于

myFunc(1);
myFunc(1, 2);
myFunc(1, 2, 3);

旧的方式应该是

myFunc(new int[]{1});
myFunc(new int[]{1, 2});
myFunc(new int[]{1, 2, 3});

据我所知,重复的参数形成 an 数组。它的所有参数必须是同一类型。以简单的方式实现上述调用应该是不可能的。出于好奇,我开始考虑运算符重载的可能性......(?)

【问题讨论】:

    标签: java arguments overloading argument-passing variadic-functions


    【解决方案1】:

    在这种情况下,在我看来,为您的“对”创建一个数据结构,然后将该类型用作您的方法的 vararg 参数是合适的。

    public void myFunc(Pair... pairs) {}
    

    你也可以使用Object...,但我看不出这种情况有什么好处,因为参数总是成对出现的。

    【讨论】:

    • 谢谢@NilsH。但是,使用时,用户必须做myFunc(new Pair(1, "one"), new Pair(2, "two"), new Pair(3, "three");,不是吗?可以缩短吗?还是以更方便的方式使用?
    • 是的,你必须这样做。如果您不希望这样,则必须使用Object...,然后检查并转换方法中的参数。但这会导致您的方法使用不正确,所以我不建议这样做。
    • 确实如此。并且使用Object... 不能保证参数的数量是偶数,对吧?
    【解决方案2】:

    创建一个将两个参数包装在一起的包装类怎么样?

    public class TwoParameter
    {
        private int intValue;
        private String stringValue;
    
        public TwoParameter(int intValue, String stringValue)
        {
            this.intValue = intValue;
            this.stringValue = stringValue;
        }
    
        // getters and setters
    }
    

    然后像这样使用它:

    myFunc(new TwoParameter(1, "one"), new TwoParameter(2, "two"));
    

    方法的签名是这样的:

    public void myFunc(TwoParameter... params){...}
    

    【讨论】:

    • 感谢@Eng.Fouad。我最关心的是,在调用时,myFunc(new TwoParameter(1, "one"), new TwoParameter(2, "two")); 似乎“长”且复杂。有没有可能以某种方式缩短它?
    【解决方案3】:

    使用其他解决方案有充分的理由,但它们都引入了一些混乱(创建所有这些对象),您可能不想让库的用户受到影响。

    您可以像这样将混乱转移到您的方法内部:

    public void example(final Object... args) {
        if (args.length % 2 != 0)
            throw new IllegalArgumentException("int, String pairs are required, but there seems to be an odd one out");
    
        for (int i = 0; i < args.length; i += 2) {
            int a = (Integer) args[i];
            String b = (String) args[i + 1];
    
            System.out.printf("%d: %s\n", a, b);
        }
    }
    

    example(1, "Hello", 2, "Goodbye", 25, "Raptors will eat you!"); 然后将产生以下输出:

    1: Hello
    2: Goodbye
    25: Raptors will eat you!
    

    【讨论】:

      【解决方案4】:

      Var args 的引入允许您向函数发送任意数量的参数。人们在其他集合/数组出现之前就对它们进行了破解。

      您可以通过自定义结构实现您想要的。结构的细节将取决于名称值对应该实现什么。这是任何 NameValue 对的通用解决方案。

      名称值对

      class NameValuePair<K,V>
      {
          private K key;
          private V value;
          public K getKey()
          {
              return key;
          }
          public void setKey(K key)
          {
              this.key = key;
          }
          public V getValue()
          {
              return value;
          }
          public void setValue(V value)
          {
              this.value = value;
          }
      }
      

      用法

      private <K,V> void method(NameValuePair<K, V>... pairs )
      {
          for (NameValuePair<K, V> nameValuePair : pairs)
          {
              K key = nameValuePair.getKey();
              V value = nameValuePair.getValue();
              // logic goes here 
          }
      }
      

      【讨论】:

      • 感谢@Deepak Bala。当我的图书馆用户使用它时,他们仍然需要NameValuePair nvp = new NameValuePair(); nvp.setKey(1); nvp.setValue("one"); method(nvp, nvp, nvp);,不是吗?是否可以编写更少的代码并让用户像我的问题中的示例一样调用method? - 看起来更人性化。
      • Java 是强类型的,所以实现你想要的唯一方法是使用Object... args。虽然这对调用者来说效果很好,但方法实现看起来很脏,因为它需要instanceof 来确定类型。我会坚持让调用者更难,而不是用instanceof编写脏代码。
      • 不客气。顺便说一句,使用Object... 意味着您不能保证名称值对:)
      猜你喜欢
      • 1970-01-01
      • 2015-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-18
      • 2019-05-19
      • 2016-02-01
      相关资源
      最近更新 更多