© 2008 Наталия Македа
Все материалы блога защищены авторским правом. Любая перепечатка или использование материалов этого блога в коммерческих целях возможна лишь с письменного согласия автора. При некоммерческом использовании ссылка на блог обязательна.

воскресенье, 27 апреля 2008 г.

Литералы, массивы, основы классов (Выпуск 2)

1. Основы языка (продолжение)

1.4. Литералы

Литерал - это костанта (не литерал - это значение определённое во время выполнения программы, например, сумма двух дитералов). Литералы могут являться значениями переменных как примитивных, так и строковых типов. Они появляются в присвоении значения (assignment) справа или в вызовах методов. Вы не можете присвоить какое-то значение литералу, то есть литералы не могут находиться слева в утверждении присвоения.

1.4.1. Литералы типа boolean

Единственные правомерные литералы типа boolean - true и false. Например:

1. boolean isBig = true;
2. boolean isLittle = false;

Здесь boolean isBig = true; - это утверждение присвоения, boolean isBig - это объявление переменной isBig типа boolean, true - это литерал. Заметьте, что литерал находится справа.

1.4.2. Литералы типа char

Литералы типа char могут быть выражены как символ в одинарных кавычках. Например:

char c = 'w';

Естественно, это справедливо только для символов, которые могут быть набраны на клавиатуре. Ещё один способ выражения символьных литералов - Unicode значение, специфицированое четырьмя шестнадцатиричными цифрами, следующими за \u. Всё выражение должно быть взято в одинарные кавычки. Например:

char c1 = '\u4567';

Специальные символы в Java выражаются так:

  • '\n' - для новой строки;
  • '\r' - для возврата каретки на начало строки;
  • '\t' - для табуляции;
  • '\b' - для возврата каретки на одну позицию назад;
  • '\f' - для новой страницы;
  • '\'' - для одинарной кавычки;
  • '\"' - для двойной кавычки;
  • '\\' - для обратной наклонной линии.

1.4.3. Целочисленные литералы

Целочисленные литералы могыт быть выражены в десятичной, восьмеричной (префикс литерала - 0) и шестнадцатиречной (префикс литерала - 0х или 0Х) форме. В последнем случае и верхний и нижний регистр может использоваться. Например, 28 может быть выражено шесьтью способами:

  • 28
  • 034
  • 0х1с
  • 0х1С
  • 0Х1с
  • 0Х1С

По умолчанию целочисленный литерал занимает 32 бита. Чтобы указать 64-хбитовый (long) литерал, нужно добавить суффикс L к литеральному выражению. (Можно указывать l и в нижнем регистре, но тогда этот суффикс выглядит как 1 (единица), что может привести к конфузам при чтении кода).

1.4.4. Литералы с плавающей точкой

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

  • десятичная точка: 1.414
  • Буква E или e, указывающая на научную нотацию: 4.23E+21
  • Суффикс F или f, указывающий на литерал типа float: 1.828f
  • Суффикс D или d, указывающий на литерал типа double: 1234d

Литерал с плавающей точкой без суффикса F или D по умолчанию является литералом типа double.

Если вы присваиваете переменной литеральное значение, например, short s = 9;, компилятор определяет размер литерала согласно типу переменной. Поэтому, только что показанное присвоение сработает без ошибок. Однако, выражение с переменными, как, например, short s1 = 9 + s;, выдаст ошибку компиляции, потому что тип выражения 9 + s есть int, а не short.

1.4.5. Строковые литералы

Строковый литерал - это последовательность символов, заключённых в двойные кавычки. Например: String s = "Characters in strings are 16-bit Unicode.";.

Java включает в себя много различных средств для определения не литеральных строковых значений, например: операторы конкатенации, некоторые сложные конструкторы для класса String. Эти способы мы рассмотрим в других номерах рассылки.

1.5. Массивы (Arrays)

Массивы в Java - это нумерованные коллекции литералов/переменных/выражений примитивных типов, указателей на объекты или других массивов. Массивы в Java однородные, то есть все элементы в массиве должны быть одного типа, за исключением случаев, разрешённых полиморфизмом. Иными словами, когда вы создаёте массив, вы должны определить тип элементов, которые могут в нём содержаться. Если тип не примитивный, а определённый через класс, то реальный массив, помимо объектов заданного класса, может содержать также объекты подклассов того класса, который был указан в объявлении массива.

Массив создаётся последовательностью трёх шагов: объявление, создание и инициализация.

В объявлении содержится имя массива, и тип его допустимых элементов. Например:

1. int[] ints; // массив, состоящий из элементов примитивного типа int
2. double[] dubs; // массив, состоящий из элементов примитивного типа double
3. Dimension[] dims; // массив из указателей на объекты (Dimension - класс в пакете java.awt)
4. float[][] twoDee; // двухмерный массив (т.е. массив массивов) из элементов типа float

Квадратные скобки могут идти и до, и после названия массива. Это также имеет место в декларации методов. Например, метод, который принимает массив элементов типа double как параметр, может быть объявлен так: takeMethod(double[] dubs) или takeMethod(double dubs[]). Метод, который возвращает массив элементов типа double, может быть объявлен как double[] returnMethod() или double returnMethod()[]. Первый способ, лично для меня, более удобен для чтения.

Заметьте, что при объявлении массива не указывается его размер, т.е. число элементов, в него входящих. Размер определяется в момент выполнения программы, когда память под массив выделяется через ключевое слово new. Например:

1. int[] ints; // Объявление массива
2. ints = new int[25]; // Создание массива во время выполнения программы


Поскольку размер массива используется только во время выполнения программы, допустимо определять размер массива через переменную, а не через литерал. Например:

1. int size = 1152 * 900;
2. int[] raster;
3. raster = new int[size];

Объявление и создание массива может быть задано одной строкой:

int[] ints = new int[25];

Когда массив создан, его элементы автоматически инициализируются значениями по умолчанию согласно Таблице 1.4.


Таблица 1.4: Значения по умолчанию для инициализации элементов массива

Тип элементаЗначение по умолчаниюТип элементаЗначение по умолчанию
byte0short0
int0long0L
float0.0fdouble0.0d
char'\u0000'booleanfalse
указатель на объектnull

Методы (и атрибуты) для Java объекта вызываются через точку: имяОбъекта.имяМетода (соответсвенно имяОбъекта.имяАтрибута).

На самом деле, массивы - это объекты, вплоть до того, что вы можете вызывать методы (через точку!) для них (в большинстве своём - это методы класса Object), хотя вы и не можете создавать подклассы для массивов.

Если вы хотите инициализировать массив другими значениями, отличными от тех, что приведены в Таблице 1.4, вы должны комбинировать объявление, создание и инпициализацию в одной строке. Например, массив из пяти опредённых чисел с плавающей точкой задаётся так:

float[] diameters = {1.1f, 2.2f, 3.3f, 4.4f, 5.5f};

Размер массива вычисляется автоматически и равен числу элементов в фигурных скобках.

Конечно же массив может быть также инициализирован явным присвоением значенией каждому элементу массива:

1. long[] squares;
2. squares = new long[6000]; // массив создан, его значения по умолчанию равны 0L
3. for (int i = 0; i < 6000; i++) {
4. squares[i] = i * i; // значения по умолчанию изменены
5. }

Если в приведенном примере размер массива поменяется (строка 2), то цикл в строке 3 может функционировать с ошибками. Для целостности программы мы перепишем строку 3 следующим образом:

3. for (int i = 0; i < squares.length; i++) { // length - встроенный атрибут массива, обозначающий длину массива


Нумерация элементов в массиве начинается с нуля (0).

В Java можно создавать непрямоугольные массивы. Поскольку многомерные массивы - это массив подмассивов, а каждый подмассив - это отдельный объект, размеры подмассивов могут быть различны. Но в этом случае будьте внимательны с итерацией по массиву.

1.6. Основы классов

Java построена на классах. Более детальное изучение классов мы разберём в других выпусках рассылки. Сейчас же обратимся к базовым понятиям.

1.6.1. Метод main()

Метод main() - это входная точка в приложениях, написанных на Java. То есть для создания приложения, вы пишете класс, в котором присутствует метод main(). Для выполнения приложения наберите в командной строке java и имя класса с методом main().

Форма задания (сигнатура) метода main() такова:

public static void main(String[] args)

Заметьте, метод main() объявлен, как общедоступный (public). Кроме того, требуется, чтобы он был также статическим (static), что означает, что он может быть вызван без создания соответсвующего объекта.

Параметр args - аргументы, которые пользователь ввёл в командную строку после имени класса. Например:

% java Mapper France Belgium

означает, что классу Mapper в командной строке было передано два аргумента France, помещённый в args[0] и Belgium - в args[1]. Имя массива args может быть заменено любым допустимым именем переменной. Главное, что его тип - массив строк.

1.6.2. Переменные и инициализация

Java поддерживает переменные двух типов, зависящих от области видимости переменной:

  1. Член класса: создаётся (уничтожается) при создании (уничтожении) объекта класса. Может иметь явное объявление доступности (общедоступный, защищённый или приватный). Вызывается через обращение к объекту класса. Видимость до закрывающей скобки класса.
  2. Автоматическая переменная метода: создаётся в методе или передаётся в него параметром. Существует во время выполнения метода и, следовательно, видна внутри метода и доступна во время выполнения метода. (Исключения бывают во внутренних классах, но о них мы поговорим в других выпусках рассылки.)

Все переменные первого типа, которым не были присвоены явные значения, автоматически инициализируются значением по умолчанию, которое зависит от типа переменной (см. Таблицу 1.4).


Член класса может быть инициализирован в строке объявления:

1. class HasVariables {
2. int x = 20; // x устанавливается в значение 20 перед вызовом конструктора класса HasVariables
3. static int y = 30; // y принимает значение 30 в момент загрузки класса HasVariables

При таком способе, нестатические переменные инициализируются перед вызовом конструктора класса, а статические переменные инициализируются в момент загрузки класса.

Автоматические переменные (также известные как локальные перемнные (local variables)) не инициализируются системой, но должны быть явно инициализированы перед использованием. Например, этот код не откомпилируется:

1. public int wrong() {
2. int i;
3. return i+5;
4. }

Ошибка компиляции в строке 3 "Variable i may not have been initialized." (Переменная i, возможно, не инициализирована) возникает часто потому, что некоторые программисты начинают использовать переменные раньше, чем инициализируют их.

1.public double fourthRoot(double d) {
2. double result;
3. if (d >= 0) { // использование раньше, чем инициализация
4. result = Math.sqrt(Math.sqrt(d)); // инициализация
5. }
6. return result;
7. }

В шестой строке компилятор выдаст ошибку "Variable result may not have been initialized". Для того, чтобы этого не произошло, перепишем строку 2 следуюшим образом:

2. double result = 0.0; // Инициализация

Теперь переменная result инициализирована. Только что показанная модификация строки 2 демонстрирует, что автоматические перемнные могут быть инициализированы в строке объявления. Хотя инициализация в отдельной строке тоже возможна.

Комментариев нет: