Лекция 03. Основы классов ####################################################################################### Классы и объекты =========================================================== Основы ----------------------------------------------------------- Классы и объекты `````````````````````````````````````````````````````````` Пример описания класса: .. code-block:: java class Point { int x, y; // экземплярные переменные Point() { // конструктор x=0; y=0; } Point (int x1,int y1) { // конструктор x=x1; y=y1; } int getX() {return x;} int getY() {return y;} } Пример создания экземпляра класса и ссылки на него: .. code-block:: java Point p1 = new Point(); Point p2 = p1; Класс **Коробка**: .. code-block:: java class Box { int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки // Конструктор Box(int w,int h,int d) { width = w; height = h; depth = d; } // вычисляем объём коробки int getVolume() { return width * height * depth; } } Hello world `````````````````````````````````````````````````````````` Еще одна версия **Hello, world!**. Создаем экземпляр класса, внутри которого объявлен **main**. .. code-block:: java public class GreetHW { String text="Hello, world!"; void print() { System.out.println(text); } public static void main(String[] args) { GreetHW greet=new GreetHW(); greet.print(); } } Статические переменные `````````````````````````````````````````````````````````` Объявление: **static ** Обращение: **.** * создаются в единственном экземпляре; * существуют вне зависимости от объектов класса; * создаются JVM в момент первого обращения к классу; * допускают обращение до создания объектов класса; Статические методы `````````````````````````````````````````````````````````` Статические методы: * могут вызывать только другие статические методы * должны обращаться только к статическим переменным * внутри статических методов нельзя использовать ссылки **this** и **super** Статический блок `````````````````````````````````````````````````````````` Объявление: .. code-block:: java static { // .... } Статический блок кода выполняется один раз при первоначальной загрузке класса .. code-block:: java public class Fruits { static String[] list = new String[3]; static { list[0]="Apple"; list[1]="Orange"; list[2]="Banana"; } public static void main(String[] args) { for(int i=0;i0) { while(!testPrime(++begin)); num--; } return begin; } } Добавим в пакет еще один файл с классом **Factorization**: .. code-block:: java package Prime; public class Factorization { public static void factorIt(int n) { for(int i=2;i*i<=n;i++) { if(n % i==0) { System.out.print(" "+i); n/=i; } } System.out.println(); } } Оба файла **Prime.java** и **Factorization.java** помещаем в каталог **Prime**. Демо-файл (класс), использующий пакет **Prime**: .. code-block:: java import Prime.*; public class Demo { public static void main(String[] args) { for(int i=1;i<15;i++) System.out.println(Prime.nPrime(1,i)); Factorization.factorIt(123456); } } Структура проекта: .. code-block:: none . ├── Demo.class ├── Demo.java └── Prime ├── Factorization.class ├── Factorization.java ├── Prime.class └── Prime.java При вложенности пакетов имена разделяют точкой, а структура каталогов на диске соответствует вложениям. .. code-block:: none anton.alg.Prime -> anton/alg/Prime Перечисления =========================================================== .. code-block:: java enum Season { WINTER, SPRING, SUMMER, AUTUMN } .. Season season = Season.SPRING; if (season == Season.SPRING) { season = Season.SUMMER; } System.out.println(season); Объявляя **enum**, мы неявно создаем класс, производный от **java.lang.Enum** Конструкция .. code-block:: none enum Season { } эквивалентна .. code-block:: none class Season extends java.lang.Enum { } Явным образом наследоваться от **java.lang.Enum** не позволяет компилятор, но: .. code-block:: none System.out.println(Season.class.getSuperclass()); дает вывод: .. code-block:: none class java.lang.Enum Класс, созданный компилятором для реализации перечисления – **enum**-класс, а возможные значения перечисляемого типа – элементы **enum**. **Элементы перечисления** - экземпляры enum-класса, доступные статически. Их статическая доступность позволяет нам выполнять сравнение с помощью оператора сравнения ссылок. .. code-block:: java Season season = Season.SUMMER; if (season == Season.AUTUMN) season = Season.WINTER; Любой enum-класс наследует **java.lang.Enum**, который содержит ряд методов полезных для всех перечислений. Пример: .. code-block:: java Season season = Season.WINTER; System.out.println("season.name()=" + season.name() + " season.toString()=" + season.toString() + " season.ordinal()=" + season.ordinal()); Вывод: .. code-block:: java season.name()=WINTER season.toString()=WINTER season.ordinal()=0 **Задача**: получить элемент enum по его строковому представлению. **Решение**: В каждом enum-классе компилятор автоматически создает специальный статический метод: .. code-block:: java public static EnumClass valueOf(String name)}, который возвращает элемент перечисления **EnumClass** с названием, равным name. Пример использования: .. code-block:: java String name = "WINTER"; Season season = Season.valueOf(name); **Результат**: переменная season будет равна **Season.WINTER** Если элемент не будет найден, то будет выброшен **IllegalArgumentException**, а если name равен null - **NullPointerException**. Иногда необходимо получить список всех элементов enum-класса во время выполнения. Для этих целей в каждом enum-классе компилятор создает метод: .. code-block:: java public static EnumClass[ ] values() Пример использования: .. code-block:: java System.out.println(Arrays.toString(Season.values())); Вывод: .. code-block:: none [WINTER, SPRING, SUMMER, AUTUMN] Обратите внимание, что ни метод **valueOf()**, ни метод **values()** не определен в классе **java.lang.Enum**. Вместо этого они автоматически добавляются компилятором на этапе компиляции enum-класса. Методы с переменным числом аргументов =========================================================== Переменное число аргументов `````````````````````````````````````````````````````````` Для указания аргумента переменной длины используют три точки (...). Например: .. code-block:: java static void vaTest(int ... v) { … } Эта синтаксическая конструкция указывает компилятору, что метод **vaTest ()** может вызываться с нулем или более аргументов. В результате **v** неявно объявляется как массив типа **int [ ]**. Таким образом, внутри метода **vaTest ()** доступ к **v** осуществляется с использованием синтаксиса обычного массива. .. code-block:: java class VarArgs { static void vaTest(int ... v) { System.out.println("Кол-во аргументов: " + v.length); for (int i=0;i