17

17


Метод Arrays.toString(), входящий в стандартную библиотеку java.util, выдает печатную версию одномерного массива.

Конечно, в данном примере массив можно определить и инициализировать в одной строке:

int[] а = new int[rand.nextlnt(20)],

Если возможно, рекомендуется использовать именно такую форму записи. При создании массива непримитивных объектов вы фактически создаете массив ссылок. Для примера возьмем класс-обертку Integer, который является именно классом, а не примитивом:

//: initialization/ArrayClassObj java // Создание массива непримитивных объектов import java.util.*;

import static net.mindview util.Print.*,

public class ArrayClassObj {

' public static void main(String[] args) { Random rand = new Random(47); Integer[] a = new Integer[rand.nextlnt(20)]; print("длина a = " + a.length); for(int i = 0; i < a.length; i++)

a[i] = rand.nextlnt(500); // Автоматическая упаковка

print(Arrays.toString(a)),

}

} /* Output (пример) длина а = 18

[55. 193. 361. 461. 429. 368, 200. 22. 207, 288. 128. 51. 89. 309. 278. 498, 361. 20] *///-

Здесь даже после вызова new для создания массива

Integer[] а = new Integer[rand nextlnt(20)];

мы имеем лишь массив из ссылок — до тех пор, пока каждая ссылка не будет инициализирована новым объектом Integer (в данном случае это делается по¬средством автоупаковки):

a[i] = rand.nextlnt(500);

Если вы забудете создать объект, то получите исключение во время выпол¬нения программы, при попытке чтения несуществующего элемента массива.

Массивы объектов также можно инициализировать списком в фигурных скобках. Существует две формы синтаксиса:

//• i niti ali zati on/ArrayInit java // Инициализация массивов import java.util *;

public class Arraylnit {

public static void main(String[] args) { Integer[] a = {

new Integer(l), new Integer(2), 3, // Autoboxing

}:

Integer[] b = new Integer[]{ new Integer(1), new Integer(2), 3. // Автоматическая упаковка

}:

System. out. pri ntl n (Arrays. toStri ng (a)); System.out println(Arrays.toString(b));

}

} /* Output- [1. 2. 3] [1. 2. 3] *///:-

В обоих случаях завершающая запятая в списке инициализаторов не обяза¬тельна (она всего лишь упрощает ведение длинных списков).

Первая форма полезна, но она более ограничена, поскольку может использо¬ваться только в точке определения массива. Вторая форма может использовать¬ся везде, даже внутри вызова метода.

Списки аргументов переменной длины

Синтаксис второй формы предоставляет удобный синтаксис создания и вызова методов с эффектом, напоминающим списки аргументов переменной длины языка С.

Такой список способен содержать неизвестное заранее количество аргументов неизвестного типа. Так как абсолютно все классы унаследованы от общего кор¬невого класса Object, можно создать метод, принимающий в качестве аргумента массив Object, и вызывать его следующим образом:

//. initialization/VarArgs.java

// Использование синтаксиса массивов

// для получения переменного списка параметров.

class А { int i; }

public class VarArgs {

static void printArray(Object[] args) { for(Object obj • args)

System.out print(obj + " "); System out printlnO,

}

public static void main(String[] args) { printArray(new Object[]{

new Integer(47), new Float(3 14), new Double(ll.ll)

}).

printArray(new 0bject[]{"pa3", "два", "три" }); pri ntArray (new Object[]{new AO, new AO, new AO});

}

} /* Output: (Sample) 47 3.14 11.11 раз два три

А@1а46еЗОА@3е25а5A@19821f*///:-

Видно, что метод print() принимает массив объектов типа Object, перебирает его элементы и выводит их. Классы из стандартной библиотеки Java при печати выводят осмысленную информацию, однако объекты классов в данном примере выводят имя класса, затем символ @ и несколько шестнадцатеричных цифр. Таким образом, по умолчанию класс выводит имя и адрес объекта (если только вы не переопределите в классе метод toString() — см. далее).

До выхода Java SE5 переменные списки аргументов реализовывались имен¬но так. В Java SE5 эта долгожданная возможность наконец-то была добавлена в язык — теперь для определения переменного списка аргументов может ис¬пользоваться многоточие, как видно в определении метода printArray:

//: initialization/NewVarArgs java // Создание списков аргументов переменной длины // с использованием синтаксиса массивов.

public class NewVarArgs {

static void printArray(Object... args) { for(Object obj • args)

System out.print(obj + " "); System.out.printlnO;

}

public static void main(String[] args) {

// Можно передать отдельные элементы printArray(new Integer(47), new Float(3 14), new Doubledl. 11));

printArray(47. 3 14F, 11.11): printArray("раз", "два", "три"): printArray(new АО. new АО, new АО): // Или массив.

printArray((Object[])new Integer[]{ 1, 2, 3, 4 }); printArray(), // Пустой список тоже возможен

}

} /* Output- (lb% match) 47 3 14 11.11 47 3 14 11.11 раз два три

A@lbab50aА@сЗс749A@150bd4d12 3 4 *///•-

Резюме

Такой сложный механизм инициализации, как конструктор, показывает, на¬сколько важное внимание в языке уделяется инициализации. Когда Бьерн Страуструп разрабатывал С++, в первую очередь он обратил внимание на то, что низкая продуктивность С связана с плохо продуманной инициализацией, которой была обусловлена значительная доля ошибок. Аналогичные проблемы возникают и при некорректной финализации. Так как конструкторы позволяют гарантировать соответствующие инициализацию и завершающие действия по очистке (компилятор не позволит создать объект без вызова конструктора), тем самым обеспечивается полная управляемость и защищенность программы.

В языке С++ уничтожение объектов играет очень важную роль, потому что объекты, созданные оператором new, должны быть соответствующим образом разрушены. В Java память автоматически освобождается сборщиком мусора, и аналоги деструкторов обычно не нужны. В таких случаях сборщик мусора Java значительно упрощает процесс программирования и к тому же добавляет так необходимую безопасность при освобождении ресурсов. Некоторые сбор¬щики мусора могут проводить завершающие действия даже с такими ресурсами, как графические и файловые дескрипторы. Однако сборщики мусора добавля¬ют издержки во время выполнения программы, которые пока трудно реально оценить из-за сложившейся исторически медлительности интерпретаторов Ja¬va. И хотя в последнее время язык Java намного улучшил свою производитель¬ность, проблема его «задумчивости» все-таки наложила свой отпечаток на воз¬можность решения языком некоторого класса задач.

Report Page