Таблица 2.1. Примитивные типы
Примитивный тип Размер, бит Минимум Максимум Тип упаковки
boolean (логические значения) — — — Boolean
char (символьные значения) 16 . Unicode 0 Unicode 216- ■1 Character
byte (байт) 8 -128 +127 Byte
short (короткое целое) 16 -215 +215-1 Short
int (целое) 32 -231 +231-1 Integer
long (длинное целое) 64 -263 +2б3-1 Long
float (число.с плавающей запятой) 32 IEEE754 IEEE754 Float
double (число с повышенной 64 IEEE754 IEEE754 Double
точностью)
Void («пустое» значение) — — — Void
Все числовые значения являются знаковыми, так что не ищите слова un¬signed.
Размер типа boolean явно не определяется; указывается лишь то, что этот тип может принимать значения true и false.
«Классы-обертки» позволяют создать в куче не-примитивный объект для представления примитивного типа. Например:
char с = 'х*,
Character ch = new Character(c),
Также можно использовать такой синтаксис:
Character ch = new CharacterC'x');
Механизм автоматической упаковки Java SE5 автоматически преобразует примитивный тип в объектную «обертку»:
Character ch = 'х'; и обратно:
char с = ch;
Причины создания подобных конструкций будут объяснены в последующих главах.
Числа повышенной точности
В Java существует два класса для проведения арифметических операций повы¬шенной точности: Biglnteger и BigDecimal. Хотя эти классы примерно подходят под определение «классов-оберток», ни один из них не имеет аналога среди примитивных типов.
Оба класса содержат методы, производящие операции, аналогичные тем, что проводятся над примитивными типами. Иначе говоря, с классами Biglnteger и BigDecimal можно делать то же, что с int или float, просто для этого использу¬ются вызовы методов, а не встроенные операции. Также из-за использования увеличенного объема данных операции занимают больше времени. Приходится жертвовать скоростью ради точности.
Класс Biglnteger поддерживает целые числа произвольной точности. Это значит, что вы можете использовать целочисленные значения любой величины без потери данных во время операций.
Класс BigDecimal представляет числа с фиксированной запятой произволь¬ной точности; например, они могут применяться для финансовых вычислений.
За подробностями о конструкторах и методах этих классов обращайтесь к документации JDK.
Массивы в Java
Фактически все языки программирования поддерживают массивы. Использо¬вание массивов в С и С++ небезопасно, потому что массивы в этих язы¬ках представляют собой обычные блоки памяти. Если программа попытается получить доступ к массиву за пределами его блока памяти или использовать память без предварительной инициализации (типичные ошибки при програм¬мировании), последствия могут быть непредсказуемы.
Одной из основных целей Java является безопасность, поэтому многие про¬блемы, досаждавшие программистам на С и С++, не существуют в Java. Массив в Java гарантированно инициализируется, к нему невозможен доступ за преде¬лами его границ. Проверка границ массива обходится относительно дорого, как и проверка индекса во время выполнения, но предполагается, что повышение безопасности и подъем производительности стоят того (к тому же Java иногда может оптимизировать эти операции).
Объекты никогда не приходится удалять
При объявлении массива объектов на самом деле создается массив ссылок, и каждая из этих ссылок автоматически инициализируется специальным значе¬нием, представленным ключевым словом null. Оно означает, что ссылка на са¬мом деле не указывает на объект. Вам необходимо присоединять объект к каж¬дой ссылке перед тем, как ее использовать, или при попытке обращения по ссылке null во время исполнения программы произойдет ошибка. Таким об¬разом, типичные ошибки при работе с массивами в Java предотвращаются за¬благовременно.
Также можно создавать массивы простейших типов. И снова компилятор га¬рантирует инициализацию — выделенная для нового массива память заполня¬ется нулями.
Массивы будут подробнее описаны в последующих главах.
Объекты никогда не приходится удалять
В большинстве языков программирования концепция жизненного цикла пере¬менной требует относительно заметных усилий со стороны программиста. Сколько «живет» переменная? Если ее необходимо удалить, когда это следует делать? Путаница со сроками существования переменных может привести ко многим ошибкам, и этот раздел показывает, насколько Java упрощает реше¬ние затронутого вопроса, выполняя всю работу по удалению за вас.
Ограничение области действия
В большинстве процедурных языков существует понятие области действия (scope). Область действия определяет как видимость, так и срок жизни имен, определенных внутри нее. В С, С++ и Java область действия устанавливается
положением фигурных скобок { }. Например:
{
int х = 12;
// доступно только х {
int q = 96;
// доступны как х, так и q
}
// доступно ТОЛЬКО X
// q находится "за пределами видимости"
}
Переменная, определенная внутри области действия, доступна только в пре¬делах этой области.
Весь текст после символов // и до конца строки является комментарием. Отступы упрощают чтение программы на Java. Так как Java относится к языкам со свободным форматом, дополнительные пробелы, табуляция и пере¬воды строк не влияют на результирующую программу.
53
Учтите, что следующая конструкция не разрешена, хотя в С и С++ она воз¬можна:
{
int х = 12, {
int х = 96. // неверно
}
}
Компилятор объявит, что переменная х уже была определена. Таким обра¬зом, возможность языков С и С++ «прятать» переменные во внешней области действия не поддерживается. Создатели Java посчитали, что она приводит к из¬лишнему усложнению программ.
Область действия объектов
Объекты Java имеют другое время жизни в сравнении с примитивами. Объект, созданный оператором Java new, будет доступен вплоть до конца области дейст¬вия. Если вы напишете:
{
String s = new Stnng("строка"); } // конец области действия
то ссылка s исчезнет в конце области действия. Однако объект String, на кото¬рый указывала s, все еще будет занимать память. В показанном фрагменте кода невозможно получить доступ к объекту, потому что единственная ссылка вы¬шла за пределы видимости. В следующих главах вы узнаете, как передаются ссылки на объекты и как их можно копировать во время работы программы.
Благодаря тому, что объекты, созданные new, существуют ровно столько, сколько вам нужно, в Java исчезает целый пласт проблем, присущих С++. В С++ приходится не только следить за тем, чтобы объекты продолжали суще¬ствовать на протяжении своего жизненного цикла, но и удалять объекты после завершения работы с ними.
Возникает интересный вопрос. Если в Java объекты остаются в памяти, что же мешает им постепенно занять всю память и остановить выполнение про¬граммы? Именно это произошло бы в данном случае в С++. Однако в Java су¬ществует сборщик мусора (garbage collector), который наблюдает за объектами, созданными оператором new, и определяет, на какие из них больше нет ссылок. Тогда он освобождает память от этих объектов, которая становится доступной для дальнейшего использования. Таким образом, вам никогда не придется «очи¬щать» память вручную. Вы просто создаете объекты, и как только надобность в них отпадет, эти объекты исчезают сами по себе. При таком подходе исчезает целый класс проблем программирования: так называемые «утечки памяти», когда программист забывает освобождать занятую память.
Создание новых типов данных
Если все является объектом, что определяет строение и поведение класса объ¬ектов? Другими словами, как устанавливается тип объекта? Наверное, для этой цели можно было бы использовать ключевое слово type («тип»); это было бы