Области видимости переменных
Переменные, объявленные в теле метода, видны от места объявления до конца блока, в котором это объявление находится. Границы блока задаются фигурными скобками {}. Поэтому в следующем примере:
{
int x = 0;
}
{
int x = 2;
}
используются две разные переменные x (первая переменная, равная 0, перестает существовать за границами своего блока). Переменные, являющимися параметрами метода, видны во всем теле метода.
Перечисленные переменные называются локальными переменными. Двух локальных переменных с одинаковыми именами и перекрывающимися областями видимости быть не должно. Нельзя, например, объявить две переменных следующим образом:
int x = 0;
{
int x = 2;
}
Нельзя, в частности, объявлять в теле метода переменную, совпадающую (по имени) с одним из параметров метода.
Конфликты имен
Конфликт имен возникает, если в одной области видимости оказываются два объекта с одинаковыми именами, причем такая ситуация является в языке разрешенной (в противном случае это не конфликт имен, а ошибка в программе).
Конфликт имен возникает, когда импортируются два пакета, содержащие классы с одинаковыми именами.
В этом случае Java отдает предпочтение классу, который был импортирован первым. Для обращения к остальным классам следует использовать их полные имена.
Java «просматривает» имена классов в следующем порядке. Сначала – классы, импортированные поодиночке. Потом – классы, определенные в данном пакете. В последнюю очередь классы из пакетов, импортируемых полностью в порядке следования команд import.
Конфликт имен возникает так же, когда имя одного из параметров метода совпадает с именем одного из атрибутов этого же класса. Такая ситуация возникает довольно часто, поскольку для метода, изменяющего значение этого атрибута, такое называние параметра довольно наглядно. Например:
class Dog {
int age;
...
public void setAge(int age) {
...
};
...
}
Такой заголовок метода setAge(int age) лучше, чем использовавшийся setAge(int a), поскольку сразу позволяет судить о назначении параметра. Однако возникает вопрос: к чему будет относиться имя age в теле этого метода – к атрибуту или к параметру.
Ответ: к параметру. Имя параметра «перекрывает» имя атрибута.
Для того, чтобы обратиться к атрибуту, следует использовать полное имя (т.е. указатель на объект this).
Реализация метода должна выглядеть следующим образом:
public void setAge(int age) {
this.age = age; // проверку диапазона параметра в этом примере проигнорируем
};
Лекция 5. Классы-коллекции
Понятие коллекции
Для хранения большого количества однотипных данных могут использоваться массивы, но они не всегда являются идеальным решением. Во-первых, длина массива задается заранее и в случае, если количество элементов заранее неизвестно, придется либо выделять память «с запасом», либо предпринимать сложные действия по переопределению массива. Во-вторых, элементы массива имеют жестко заданное размещение в его ячейках, поэтому, например, удаление элемента из массива не является простой операцией.
В программировании давно и эффективно используются такие структуры данных как стек, очередь, список, множество и т.д., объединенные общим названием коллекция.
Коллекция – это группа элементов с операциями добавления, извлечения и поиска элемента. Механизм работы операций существенно различается в зависимости от типа коллекции. Например, элементы стека упорядочены в последовательность, добавление нового элемента может происходить только в конец этой последовательности, и получить можно только элемент, находящийся в конце (то есть, добавленный последним). Очередь, напротив, позволяет получить лишь первый элемент (элементы добавляются в один конец последовательности, а «забираются» с другого). Другие коллекции (например, список) позволяют получить элемент из любого места последовательности, а множество вообще не упорядочивает элементы и позволяет (помимо добавления и удаления) узнать, содержится ли в нем данный элемент.
Язык Java предоставляет библиотеку стандартных коллекций, которые собраны в пакете java.util, поэтому нет необходимости программировать их самостоятельно.
При работе с коллекциями главное избегать ошибки начинающих – пользоваться наиболее универсальной коллекцией вместо той, которая необходима для решения задачи – например, списком вместо стека. Если логика работы программы такова, что данные должны храниться в стеке (появляться и обрабатываться в обратной последовательности), следует использовать именно стек. В этом случае вы не сможете нарушить логику обработки данных, обратившись напрямую к середине последовательности, а значит, шанс появления трудно обнаруживаемых ошибок резко уменьшается.
Чтобы выбрать коллекцию, которая лучше всего подходит условию задачи, необходимо знать особенности каждой из них. Эти знания являются обязательными для любого программиста, поскольку без применения тех или иных коллекций редко обходится любая современная задача. Некоторые сведения вы сможете почерпнуть из дальнейшего изложения.
Классы-коллекции
Коллекции в библиотеке java.util представлены набором классов и интерфейсов.
Каждый класс реализует некоторую коллекцию со специфичным для нее набором операций доступа к элементам. Чтобы использовать коллекцию в своей программе, нужно создать объект соответствующего класса.
Элементы большинства коллекций имеют тип Object. Это значит, что (в отличие от обычного массива) нет необходимости заранее указывать тип элементов, которые будете помещать в коллекцию. Можно добавлять в нее объекты любого класса, поскольку все классы являются наследниками класса Object, более того – в одной коллекции могут храниться объекты совершенно разных классов.
Конечно, это может привести и к трудностям. Если вы захотите совершать какие-то операции над элементом коллекции (а помещаются в коллекцию объекты именно для того, чтобы потом их извлекать и обрабатывать), нельзя воспользоваться его методами, не приведя объект к его «настоящему» классу посредством явного приведения типов.
Например, есть объект класса String (обычная строка) и вы хотите добавить его в стек stack с помощью метода push(Object item):
String str = "Ценная строка";
stack.push(str);
Коллекция, хранящая элементы типа Object, сразу же «забывает», что ваш объект – строка, поскольку при его добавлении было осуществлено автоматическое приведение типа String к типу Object. Можно извлечь объект методом pop(), но чтобы вернуть ему прежний тип (а без этого нельзя воспользоваться ни одним из его методов), придется осуществить явное преобразование оператором (String):
str = (String)stack.pop();
Это не является проблемой, просто нужно помнить, объекты какого класса вы помещаете в коллекцию и выполнять соответствующее преобразование типа над каждым побывавшим в коллекции элементом.
Но если попытаться привести объект к неправильному типу, возникнет ошибка в программе:
stack.push(new Dog("Шарик", 12)); // помещаем в стек собаку
str = (Mouse)stack.pop(); // вынимаем собаку и пытаемся объявить ее мышью, но эти классы не связаны наследованием и программа выдаст ошибку во время выполнения
Так что, возможностью помещать в коллекцию любые объекты, воспользоваться скорее всего не получится. Представьте себе, что программа должна «помнить», что первый элемент списка – строка, второй – число, третий – собака, четвертый – опять число. И обработать их все в цикле она, наверное, не сможет, поскольку у этих объектов нет общих методов. В результате теряются все преимущества использования коллекции. Поэтому в каждую коллекцию следует помещать объекты только одного класса (и производных от него).
Дата добавления: 2017-01-26; просмотров: 1229;