Чтение онлайн

ЖАНРЫ

Java: руководство для начинающих
Шрифт:

Помимо аргумента переменной длины, в методе можно также указывать и обычные аргументы, но при одном условии: аргумент переменной длины должен быть указан последним. Например, приведенное ниже объявление метода является вполне допустимым, int dolt(int a, int b, double с, int ... vals) {

В данном случае первые три аргумента, передаваемые при вызове метода dolt , будут соответствовать первым трем параметрам. А остальные аргументы будут считаться относящимися к параметру переменной длины vals.

Ниже приведен переработанный вариант метода vaTest , в котором используются как обычные аргументы, так и аргументы переменной длины. // Использование аргументов переменной длины // вместе с обычными аргументами, class VarArgs2 { // Здесь msg - обычный аргумент, // a v - аргумент переменной длины. static void vaTest(String msg, int ... v) { System.out.println(msg + v.length); System.out.println("Contents: ") ; for(int i=0; i < v.length; i++) System.out.println(" arg " + i + ": " + v[i]); System.out.println; } public static void main(String args[]) { vaTest("One vararg: ", 10); vaTest ("Three varargs: ", 1, 2, 3); vaTest("No varargs: "); } }

Выполнение

этого фрагмента кода дает следующий результат: One vararg: 1 Contents: arg 0: 10 Three varargs: 3 Contents: arg 0: 1 arg 1: 2 arg 2: 3 No varargs: 0 Contents:

He следует, однако, забывать, что аргумент переменной длины должен быть указан последним. Например, следующее объявление метода недопустимо: int dolt(int a, int b, double с, int ... vals, boolean stopFlag) { // Ошибка!

В данном примере сделана попытка указать обычный аргумент после аргумента переменной длины.

Существует еще одно ограничение, которое следует соблюдать: аргументы переменной длины можно указать в методе только один раз. Например, приведенное ниже объявление метода составлено неверно. int dolt(int a, int b, double с, int ... vals, double ... morevals) { // Ошибка!

Ошибкой в данном случае является попытка указать два разных типа аргументов переменной длины. Перегрузка методов с аргументами переменной длины

Если требуется, то метод, принимающий переменное число аргументов, можно перегрузить. Например, в следующей программе трижды перегружается метод vaTest : // Перегрузка метода с аргументами переменной длины, class VarArgs3 { // Первый вариант метода vaTest. static void vaTest(int ... v) { System.out.println("vaTest (int ...): " + "Number of args: " + v.length); System.out.println("Contents: ") ; for(int i=0; i < v.length; i++) System.out.println(" arg " + i + ": " + v[i]); System.out.println; } // Второй вариант метода vaTest. static void vaTest(boolean ... v) { System.out.println("vaTest(boolean ...): " + "Number of args: " + v.length); System.out.println("Contents: ") ; for(int i=0; i < v.length; i++) System.out.println(" arg " + i + ": " + v[i]); System.out.println; } // Третий вариант метода vaTest. static void vaTest(String msg, int ... v) { System.out.println("vaTest(String, int ...): " + msg + v.length); System.out.println("Contents: ") ; for (int i=0; i < v.length; i++) System.out.println(" arg " + i + ": " + v[i]); System.out.println; } public static void main(String args[]) { vaTest(1, 2, 3) ; vaTest("Testing: ", 10, 20); vaTest(true, false, false); } }

Выполнение этой программы дает следующий результат: vaTest(int ...): Number of args: 3 Contents: arg 0: 1 arg 1: 2 arg 2: 3 vaTest(String, int ...): Testing: 2 Contents: arg 0: 10 arg 1: 20 vaTest(boolean ...): Number of args: 3 Contents: atg 0: true arg 1: false arg 2: false

В приведенном выше примере программы демонстрируются два способа перегрузки методов с аргументами переменной длины. Во-первых, типы параметров аргументов длины у перегружаемых методов могут отличаться. Это демонстрируют варианты метода vaTest (int . . .) и vaTest (boolean . . .). Напомним: многоточие обозначает, что соответствующий аргумент должен рассматриваться как массив указанного типа. Следовательно, как и при перегрузке обычных методов указываются разные типы параметров, так и перегрузке методов с аргументами переменной длины задаются разные типы подобных аргументов. Исполняющая система Java использует эти данные для правильного выбора вызываемого метода.

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

При перегрузке методов с аргументами переменной длины может возникнуть довольно неожиданная ошибка. А возникает она вследствие неоднозначности в выборе метода. Рассмотрим в качестве примера следующую

программу: // Перегрузка метода с аргументами переменной длины //и неоднозначность выбора метода. // //В этой программе имеется ошибка, и // поэтому она не будет компилироваться, class VarArgs4 { // Использование аргумента переменной длины типа int. static void vaTest(int ... v) { // ... } // Использование аргумента переменной длины типа boolean. static void vaTest(boolean ... v) { // ... } public static void main(String args[]) { vaTest(1, 2, 3); // OK vaTest(true, false, false); // OK vaTest; // Ошибка вследствие неоднозначности! } }

В этой программе перегрузка метода vaTest указана правильно, но она не компилируется. И причиной тому служит следующий вызов: vaTest; // Ошибка: неоднозначность вызова!

Переменное число аргументов подразумевает в том числе и нулевое их число, и поэтому приведенный выше вызов может быть интерпретирован и как vaTest (int . . .), и как vaTest (boolean . . .). Оба вызова допустимы, и поэтому обращение к данному методу неоднозначно.

Рассмотрим еще один пример неоднозначности при обращении к методу. Из приведенных ниже вариантов метода vaTest невозможно однозначно выбрать требуемый, несмотря на то, что в одном из вариантов метода, помимо аргумента переменной длины, присутствует также обычный аргумент. static void vaTest(int ... v) { // ... static void vaTest(int n, int ... v) { // ...

И хотя списки аргументов у обоих вариантов метода vaTest отличаются, компилятор все равно не может правильно выбрать вариант для следующего вызова: vaTest (1)

В самом деле, не понятно, нужно ли преобразовать этот вызов в vaTest (int . . .) с одним аргументом переменной длины или же в вызов vaTest (int, int . . .) без аргументов переменной длины? В итоге возникает неоднозначная ситуация.

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

Допустим, имеется следующий фрагмент кода:class X { private int count; Является ли допустимым приведенный ниже фрагмент кода?class Y { public static void main(String args[]) { X ob = new X; ob.count = 10;.

Модификатор доступа должен __ объявлению члена класса.

Помимо очереди, в программах часто используется структура данных, которая называется стеком. Обращение к стеку осуществляется по принципу “первым пришел — последним обслужен44. Стек можно сравнить со стопкой тарелок, стоящих на столе.Последней берется тарелка, поставленная на стол первой. Создайте класс Stack, реализующий стек для хранения символов. Используйте методы push и pop для манипулирования содержимым стека. Пользователь класса Stack должен иметь возможность задавать размер стека при его создании. Все члены класса Stack, кроме методов push и pop , должны быть объявлены как private. (.Подсказка: в качестве заготовки можете воспользоваться классом Queue, изменив в нем лишь способ доступа к данным.)

Допустим, имеется следующий класс:class Test { int а; Test(int i) { a = i; } } Напишите метод swap , реализующий обмен содержимым между двумя объектами типа Test, на которые ссылаются две переменные данного типа.

Правильно ли написан следующий фрагмент кода?class X { int meth(int a, int b) { ... } String meth(int a, int b) { ... }

Напишите рекурсивный метод, отображающий строку задом наперед.

Допустим, все объекты класса должны совместно пользоваться одной и той же переменной. Как объявить такую переменную?

Для чего может понадобиться статический блок?

Что такое внутренний класс?

Допустим, требуется член класса, к которому могут обращаться только другие члены этого же класса. Какой модификатор доступа следует использовать в его объявлении?

Имя метода и список его параметров вместе составляют __ метода.

Если методу передается значение типа int, то в этом случае используется передача параметра по __.

Создайте метод sum с аргументами переменной длины для суммирования передаваемых ему значений типа int. Метод должен возвращать результат суммирования. Продемонстрируйте его в действии.

Поделиться с друзьями: