Varargs помощью функции языка

Вы когда-нибудь найти себя в такую ситуацию? Вы должны пройти во многих случаях и того же типа объекта метода, но вы не знаете, во время компиляции, сколько экземпляров будет. В прошлом, единственным способом справиться с этой ситуацией было расслоение этих объектов в массиве или другие коллекции. Вместе с J2SE 5.0, теперь у вас есть дополнительное удобство использования переменных параметров арность, менее формально известный как varargs. В этот совет, вы узнаете, почему это хорошая идея, чтобы воспользоваться varargs как клиент API. Подсказка также предостерегает против введения varargs к API, что вы можете создавать, если это оправдано его.

Давайте начнем с примера, который иллюстрирует использование varargs. В следующей программе VarGreeter, метод printGreeting () принимает неопределенного числа объектов String в качестве входных данных. Об этом свидетельствует использование Многоточие в декларации параметра String … имена. В целом, метод может иметь не более одного параметра, который является vararg, он должен быть последним параметром принятым методом, и оно обозначается тип объекта, набор эллипсов (…), а имя переменной.


  class VarGreeter {



       public static void printGreeting(String... names) {

          for (String n : names) {

              System.out.println("Hello " + n + ". ");

          }

       }



       public static void main(String[] args) {

          printGreeting("Paul""Sue");

       }

   }

В VarGreeter, метод printGreeting () вызывается с призывом printGreeting ( "Поле", "Сью"). Если вы запустите VarGreeter, вы получите сообщение:

Hello Paul.
Hello Sue.

Измените строку в VarGreeter которая требует printGreeting (), чтобы иметь столько объект String аргументы, как вам нравится. Каждое имя, которое вы передаете в встретит. PrintGreeting () работает себе путь через любые коллекции строк прошло, и встречает каждый по очереди. Что, пожалуй, наиболее ярким является то, что это работает, если прошло не строка. Вы можете убедиться в этом, основные изменения () на следующую, и провести повторное VarGreeter.


   public static void main(String[] args) {

    printGreeting();

   }

На этот раз у вас не будет выхода, потому что никто не приветствовать. Этот пример иллюстрирует использование соответствующих varargs. Вы не указано количество объектов строк в процессе таким же образом.

Во время компиляции vararg преобразуется в массив. Вы можете видеть, что printGreeting () использует улучшенный цикл для итерации по массиву. Использование vararg отличается использованием массива. Следующие несколько примеров подчеркивают сходства и различия. Сначала рассмотрим VarGreeter2:


   public class VarGreeter2 {

      public static void printGreeting(String... names) {

          for (String n : names) {

              System.out.println("Hello " + n + ". ");

          }

      }



      public static void main(String[] args) {

          printGreeting(args);

      

   }

Главное то, что вы можете передать в массив в качестве параметра. Аргументы переменная представляет собой массив типа String. Выполнить эту версию с помощью команды:

java VarGreeter2 Paul Sue

и вы получите тот же результат, как и прежде:

Hello Paul.
Hello Sue

Вы можете экспериментировать с различным числом аргументов командной строки. Вы даже можете перейти в не аргументы. Обычно, вам нужен охранник пункт, чтобы убедиться, что аргументы не имеют нулевой длины. При необходимости, вы должны проверить правильность ввода. В этом случае, нет такого требования. PrintGreeting () метод может обрабатывать нуля или более строк, передаваемых в виде списка строк или передается в качестве одного массив строк.

Теперь рассмотрим VarGreeter3. Здесь вы увидите, что вы даже можете изменить подписания основного (). Хотя нет никаких оснований для этого, канонической общественности статической Void Main (string [] аргументы) может быть изменен на статический общественности Void Main (string … аргументы):


   public class VarGreeter3 {



       public static void printGreeting(String... names) {

          for (String n : names) {

               System.out.println("Hello " + n + ". ")

          }

       }



       public static void main(String... args) {

          printGreeting(args);

       }

   }

Запуск VarGreeter3 с помощью команды:

java VarGreeter3 Paul Sue

и вы получите тот же результат, как и прежде:

Hello Paul.
Hello Sue.

Использование "Основной (String. .. аргументы)" легче ссылаться непосредственно из основных Java. Это может быть полезным для написания юнит-тестов вашего основного () метод.

До сих пор вы не видели никакой разницы между явным объявлением printGreeting (), используя varargs и использование массива. Теперь пришло время посмотреть на разницу. Изменить подпись printGreeting (String … имена) до printGreeting (String [] имена). Заметьте, что в VarGreeter4, вы можете перейти в массив строк с призывом printGreeting (аргументы):


   public class VarGreeter4 {



       public static void printGreeting(String[] names) {

          for (String n : names) {

              System.out.println("Hello " + n + ". ")

          }

       }



       public static void main(String... args) {

          printGreeting(args);

       }

   }

Вы по-прежнему получать те же результаты как и прежде, если вы выполните команду:

java VarGreeter4 Paul Sue

Разница, если вы попробуете вызвать printGreeting помощью что-то вроде printGreeting ( "Поле", "Сью"), как показано в VarGreeter5:


   public class VarGreeter5 {



       public static void printGreeting(String[] names) {

          for (String n : names) {

              System.out.println("Hello " + n + ". ");

          }

       }



       public static void main(String... args) {

          printGreeting("Paul""Sue")

       }

   }

Попробуйте откомпилировать VarGreeter5. Он не будет компилироваться:

javac VarGreeter5.java
VarGreeter5.java:10: printGreeting(java.lang.String[]) in
VarGreeter5 cannot be applied to
(java.lang.String,java.lang.String)
printGreeting("Paul", "Sue");
^
1 error

Урок заключается в том, что varargs дать вам большую свободу действий, что и клиент из API.

Внимание: Следующие примеры иллюстрируют некоторые из опасностей, представляя varargs к API. Это не менее важно знать, когда нецелесообразно использовать технику, как это знать, когда его использовать.

GridLayout класс имеет три конструктора, один принимает четыре аргумента, один принимает два аргумента, а один не принимает аргументов. Конструктор с двумя аргументами позволяет пользователю указать количество строк и столбцов в результате сетке. Конструктор с четырьмя аргументы также дает пользователю возможность указать размер горизонтальный разрыв между рядами и размеры вертикального разрыва между колоннами. Два аргумента конструктора принимает эти ценности к нулю. Конструктор без аргументов предоставляет по умолчанию для количества строк и столбцов. Следующая программа, PreVarGridLayout, представляет собой упрощенную класс с трех конструкторов, которые определяются во многом так же, как и для GridLayout класс:


   class PreVarGridLayout {



      PreVarGridLayout() {

         this(11);

      }



      PreVarGridLayout(int rows, int cols) {

         this(rows, cols, 00);

      }  



      PreVarGridLayout(int rows, int cols, int hgap, int vgap) {

         System.out.println("Create a grid with rows = "

         + rows + " and cols = " + cols + ", the hgap = "

         + hgap + " and the vgap = " + vgap + ".");

      }



      public static void main(String[] args) {

         System.out.println("Call no arg constructor:");

         new PreVarGridLayout();

         System.out.println("Call two arg constructor: 2,3");

         new PreVarGridLayout(23);

         System.out.println

            ("Call four arg constructor: 4,5,6,7");

         new PreVarGridLayout(4567);

      }

   }

В основной (), вы можете видеть, что называется каждый конструктор. Если вы запустите PreVarGridLayout, вы получите следующий результат:

Call no arg constructor:
Create a grid with rows = 1 and cols = 1, the hgap = 0 and
the vgap = 0.
Call two arg constructor: 2,3
Create a grid with rows = 2 and cols = 3, the hgap = 0 and
the vgap = 0.
Call four arg constructor: 4,5,6,7
Create a grid with rows = 4 and cols = 5, the hgap = 6 and
the vgap = 7.

Вы можете превратить программу, чтобы воспользоваться varargs, как показано в VarGridLayout:


   public class VarGridLayout {

   

      VarGridLayout(Integer... size) {

         Object temp[] {1,1,0,0};

         System.arraycopy(size, 0, temp, 0, size.length);

         System.out.printf("Create a grid with rows = %d " +

         "and cols = %d, the hgap = %d and the vgap = " +

         "%d. \n", temp);

      }

   

      public static void main(String[] args) {

         System.out.println("Call no arg constructor:");

         new VarGridLayout();

         System.out.println("Call two arg constructor: 2,3");

         new VarGridLayout(23);

         System.out.println(

            "Call four arg constructor: 4,5,6,7");

         new VarGridLayout(4567);

      }

    }

Есть никаких изменений в основные (), поэтому конструкторы называют в то же время в VarGridLayout как они были в PreVarGridLayout, то есть до введения varargs. Разница в том, что теперь существует единая конструктор. Конструктор принимает нуля, два или четыре аргумента как прежде и печатает тот же результат. Обратите внимание, что на этот раз Е () используется для записи в выходной поток. Е () использует объект varargs. Это позволяет вам перейти в темпе в качестве последнего параметра Е (). Метод лечит Темп как массив типа Integer.

Но есть одна серьезная проблема в использовании varargs таким образом. Вы можете видеть проблему, изменив последнюю строку из основных () в PreVarGridLayout к:

new PreVarGridLayout(4,5,6,7,8);

и в VarGridLayout к:

new VarGridLayout(4,5,6,7,8);

Перекомпилируйте PreVarGridLayout:

javac PreVarGridLayout.java
PreVarGridLayout.java:23: cannot find symbol
symbol  : constructor PreVarGridLayout(int,int,int,int,int)
location: class PreVarGridLayout
new PreVarGridLayout(4,5,6,7,8);
^
1 error

Вы получите ошибку компиляции, потому что подпись не соответствует ни одному из имеющихся конструкторов PreVarGridLayout. В самом деле, если вы используете IDE с кодом смысле она должна быть в состоянии сигнала до компиляции, что этого не будет компилироваться.

Теперь скомпилируйте VarGridLayout. Вы не получите предупреждений во время компиляции, потому что ваш конструктор может принимать ноль или более Integer объекты в качестве параметров. Если вы запустите VarGridLayout, вы получите ArrayIndexOutOfBoundsException.

Вы могли бы предоставить чек, который size.length либо равна нулю, два или четыре, и бросить свой собственный исключением иначе. Дело в том, что в результате этой проверки оставляется вам, оно не исполняется компилятором. Это означает, что разработчикам, использующим код не будет иметь поддержки в процессе компиляции или письменной время для принятия правильных вызовов. Такой урок не varargs использовать для этой цели.

Другим вопросом является использование varargs зная, какой метод будет вызываться, если, как представляется, конкурирующие подписей. В следующем классе, WhichOne, есть три конструкторов. Первый конструктор принимает vararg аргумент, второй принимает два аргумента Int, а третье занимает два целочисленных аргументов:


   public class WhichOne {





      WhichOne(Integer... size) {

         System.out.println("Var Args version.");

      }



      WhichOne(int i, int j) {

         System.out.println("Version with int args.");



      }



      WhichOne(Integer i, Integer j) {

         System.out.println("Version with Integer args.");

      }



      public static void main(String[] args) {

         System.out.println("Call w/ two arg:2,3");

         new WhichOne(23);

         System.out.println("Call w/ Integer two arg: 2,3");

         new WhichOne(new Integer(2)new Integer(3));

      }



   }

Запуск WhichOne, и вы увидите следующее сообщение:

Call w/ two arg:2,3
Version with int args.
Call w/ Integer two arg: 2,3
Version with Integer args.

Даже с varargs версию конструктора, наиболее конкретно-называется соответствие конструктор. Исключить второе и третье конструкторов, чтобы WhichOne выглядит следующим образом:


   public class WhichOne {





      WhichOne(Integer... size) {

         System.out.println("Var Args version.");

      }



      public static void main(String[] args) {

         System.out.println("Call w/ two arg:2,3");

         new WhichOne(23);

         System.out.println("Call w/ Integer two arg: 2,3");

         new WhichOne(new Integer(2)new Integer(3));

      }



   }

Перезапуск WhichOne. Вы должны увидеть следующее сообщение:

Call w/ two arg:2,3
Var Args version.
Call w/ Integer two arg: 2,3
Var Args version.

В отсутствие более конкретных строителей, varargs версия называется обеих новых WhichOne (2,3) и новым WhichOne (новая Integer (2), Нью-Integer (3)). Она играет важную роль в построении API, чтобы дать понять клиенту, как вызвать желаемый метод. Такой урок здесь избегать использования varargs на перегруженных методов.

Следует повторить, что преимущества использования varargs является то, что в качестве клиента по API, вы можете вызвать метод с помощью последовательности экземпляров объектов определенного типа или массив. У вас есть свобода для посылки вызова с помощью любого количества экземпляров этого типа. Есть также опасность использования varargs. Возможно, вы захотите, чтобы избежать предоставления методах, которые используют varargs, когда важно, чтобы указать количество записей или для предотвращения autoboxing.

Для получения дополнительной информации о varargs см. документ Varargs.

Copyright (C) 2004-2005 Sun Microsystems, Inc
Все права защищены.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>