Конструктор
Конструктор инициализирует объект непосредственно во время создания. Имя конструктора совпадает с именем класса, включая регистр, а по синтаксису конструктор похож на метод без возвращаемого значения.
В отличие от метода, конструктор никогда ничего не возвращает.
Конструктор определяет действия, выполняемые при создании объекта класса, и является важной частью класса. Как правило, программисты стараются явно указать конструктор. Если явного конструктора нет, то Java автоматически создаст его для использования по умолчанию. Когда мы реализовывали класс Box, то никакого конструктора не создавали.
Добавим в класс конструктор, который просто установит начальные значения для коробки.
Мы временно удалили метод setDim() и добавили конструктор. Посмотрим, что получится:
Программа выведет объём коробки, хотя мы не задавали никаких размеров для неё. Благодаря конструктору любая создаваемая коробка будет иметь какой-то зафиксированный объём.
Естественно, вы можете вернуть обратно метод setDim() (см. статью про классы) и установить свои размеры для коробки:
Теперь вам должно быть ясно, что когда после ключевого слова new мы пишем имя класса со скобками, то на самом деле мы вызываем конструктор класса.
Подобно любому методу, у конструктора могут быть аргументы. В аргументах конструктора передаются параметры для инициализации объекта. Например, если у класса Cat имеется конструктор, который получает в качестве аргумента целое число, обозначающее возраст кота, то объекты Cat будут создаваться следующим образом:
Если Cat(int) является единственным конструктором класса, то компилятор не позволит создавать объекты Cat каким-либо другим способом.
Однако вернёмся к коробкам для котов. Созданный нами конструктор не особо полезен, так как создаёт одинаковые коробки. Создадим конструктор с параметрами в классе Box и закомментируйте первый конструктор без параметров:
Если класс содержит один конструктор с параметрами, то вам придётся обязательно указать значения при объявлении класса:
Кстати, с таким конструктором метод setDim() нам уже не нужен. Мы можем задать размеры коробки сразу в конструкторе. Так как скорее всего коробка постоянна и не меняет своих размеров, то метод, пожалуй, лишний. Но если мы будем менять размеры коробки, то метод придётся оставить.
То есть, мы видим, что конструкторы поддерживают перегрузку, как и методы.
Например, мы можем создать ещё один конструктор специально для коробки в виде куба, где все стороны равны:
Вычисляем размер куба:
Используем объект в качестве параметров
Мы пока использовали в качестве параметров в конструкторах простые типы. Но можно передать и объект самого класса. Добавим ещё один конструктор:
В коде программы можно воспользоваться конструктором следующим образом:
Класс Box (исходник)
Вызов перегруженных конструкторов через this()
Имея дело с перегруженными конструкторами, удобно один конструктор вызывать из другого через ключевое слово this. При выполнении конструктора this() сначала выполняется перегруженный конструктор, который соответствует списку параметров. Затем выполняются операторы, находящиеся внутри исходного конструктора, если таковые существуют. Вызов конструктора this() должен быть первым оператором в конструкторе.
Для начала создадим класс, который не использует конструктор this(), чтобы понять разницу.
Мы создали класс с тремя конструкторами. Перепишем класс, используя конструктор this().
Вызов конструктора Cat(8) приводит к выполнению конструктора this(8, 8), что равнозначно вызову конструктора Cat(8, 8).
Что происходит при выполнении оператора:
В этом случае вызывается конструктор this(0), что приводит к выполнению конструктора Cat(0), поскольку именно эта версия конструктора подходит по списку параметров. При этом конструктор Cat(0) по сути вызывает конструктор Cat(0, 0).
Использование перегруженных конструкторов через конструктор this() позволяет исключить дублирование кода, уменьшая время загрузки классов.
Но следует быть осторожным, так как конструкторы, которые вызывают конструктор this(), выполняются немного медленнее.
Закрытый конструктор
Иногда класс создаётся только для хранения каких-то статических полей и статических методов. Таким классам принято давать имена Utils, но это не обязательно. Такому классу не нужен конструктор, но если автор класса его не создал, то система сама создаст конструктор по умолчанию. Такой конструктор не имеет смысла, а также может послужить источником ошибок. Чтобы предохраниться от подобной проблемы вы сами явно должны создать пустрой конструктор и сделать его закрытым.
Строка throw new AssertionError() не является обязательной, но она поможет выявить ошибку, если вы вызовете конструктор в самом классе. Компилятор пропустит такой вариант, но программа завершится с ошибкой.
Подкласс для данного класса вы создать не сможете.
Конструкторы в Java
Шаг за шагом
Итак, чтобы объяснить нагляднее, представим, как работает программа.
1. Вы создаете основное «тело» программы, прописывая метод main:
2. Допустим, Вам нужен объект класса Cat. Класс Cat у вас уже есть, и выглядит он так:
Вы пишете строку, которая должна создать объект класса Cat:
3. В тот момент, когда программа приступает к созданию объекта cat1, она идет в class Cat:
Тут-то и появляется необходимость в конструкторах. Ведь в первую очередь Java ищет именно конструкторы, которые укажут, как именно создавать объект.
Явные и неявные конструкторы
Преимущество 1. Контроль над вводом данных.
Сначала, дайте посмотрим на изображение. Какие отличия Вы видите?
Явно прописывая конструктор, Вы получаете возможность регулировать, какие параметры и в каком количестве нужно задать для создания объекта определенного класса.
Преимущество 2. Меньше строчек кода.
Вы заметили, как конструктор уменьшает количество строк в коде? Сравните:
Объекты и Конструкторы
1. Создание объекта
Вот мы и дошли до созданий объектов. Вы уже сталкивались с этим ранее, просто сейчас мы разберем эту тему более подробно. На самом деле создавать объекты очень просто.
Чтобы создать объект, нужно использовать оператор new. Выглядит создание объекта примерно так:
Чаще всего, сразу после создания объекта, ссылку на него мы сохраняем в переменную, которая тоже очень часто имеет такой же тип, что и создаваемый объект. Поэтому обычно вы видите код создания объекта похожим на такой:
| Код | Примечание |
|---|---|
| Создание объекта типа Object | |
| Создание объекта типа Cat | |
| Создание объекта типа Scanner |
Очень часто программисты называют переменные таким же именем, что и классы, только с маленькой буквы. Программиста-новичка такой код может сбивать с толку:
По факту в этом коде нет ничего страшного — это самый обычный код, в котором создается переменная и тут же инициализируется объектом ее же типа.
Слева от знака равенства — создание переменной. Справа — создание объекта. Все.
2. Конструктор
Вы, наверное, часто видели, что при создании объекта в него передаются какие-то параметры. Причем в некоторые объекты параметры передаются, а в некоторые — нет. Как вообще работает весь этот механизм с параметрами?
Тут тоже все просто: у каждого класса есть специальный метод (или методы), которые отвечают за обработку параметров при создании объекта. Такие методы называются конструкторы. А один метод, соответственно, конструктор.
Отличить метод-конструктор от обычного метода в коде несложно. Такой метод обладает двумя особенностями:
Общий вид его обычно такой:
| Код | Примечание | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Класс Point Конструктор класса Point | |||||||||||
| Так можно |
| А так — нельзя. Код не скомпилируется. |
| И так нельзя. Код не скомпилируется. |
У класса Cat всего один конструктор с параметрами name и age. Т.к. других конструкторов нет, вы обязаны при создании объекта передать в качестве параметров имя ( name ) и возраст ( age ) кота. Вы не можете не передать параметры в конструктор.
4. Несколько конструкторов
Однако если вам нужно, вы можете добавить в класс несколько конструкторов. Никакого ограничения на количество конструкторов или их параметров нет. При создании объекта компилятор сам подберет подходящий по параметрам конструктор
| Код | Примечание |
|---|---|
| Так можно: вызовется первый конструктор | |
| Так можно: вызовется второй конструктор | |
| А так — нельзя. Код не скомпилируется. |
Мы решили учесть ситуацию, что возраст кота может быть неизвестен. Для этого случая добавили в код специальную константу — UNKNOWN и конструктор, который принимает только один параметр — имя кота.
Если переменной age не присвоить никакого значения, она будет хранить значение по умолчанию == 0. А ведь найденному на улице котенку вполне себе может быть 0 полных лет. Поэтому ноль в переменой age совсем не обязательно обозначает «неизвестный возраст».
5. Конструктор по умолчанию
Если вы хотите, чтобы объекты вашего класса создавались без каких-либо параметров, вам нужно, чтобы у вашего класса был объявлен конструктор без параметров.
Конструктор без параметров — это не обязательно конструктор без кода, он вполне себе может содержать код, который инициализирует переменные класса стартовыми значениями:
| Код | Примечание |
|---|---|
| Так можно: вызовется первый конструктор | |
| Так можно: вызовется второй конструктор |
Конструктор по умолчанию
Есть очень важный момент, который вам следует знать и помнить.
Если у вашего класса вообще нет ни одного конструктора, компилятор добавит вам в класс конструктор-по-умолчанию – конструктор без параметров и кода, но с модификатором public.
Однако, если в вашем классе есть хотя бы один конструктор, конструктор-по-умолчанию уже добавляться не будет – вам нужно будет дописать его самостоятельно.
Классы. Объектно-ориентированное программирование
Классы и объекты
Java является объектно-ориентированным языком, поэтому такие понятия как «класс» и «объект» играют в нем ключевую роль. Любую программу на Java можно представить как набор взаимодействующих между собой объектов.
Класс определяется с помощью ключевого слова сlass :
Для хранения состояния объекта в классе применяются поля или переменные класса. Для определения поведения объекта в классе применяются методы. Например, класс Person, который представляет человека, мог бы иметь следующее определение:
Теперь используем данный класс. Для этого определим следующую программу:
Как правило, классы определяются в разных файлах. В данном случае для простоты мы определяем два класса в одном файле. Стоит отметить, что в этом случае только один класс может иметь модификатор public (в данном случае это класс Program), а сам файл кода должен называться по имени этого класса, то есть в данном случае файл должен называться Program.java.
Конструкторы
Если в классе не определено ни одного конструктора, то для этого класса автоматически создается конструктор без параметров.
Выше определенный класс Person не имеет никаких конструкторов. Поэтому для него автоматически создается конструктор по умолчанию, который мы можем использовать для создания объекта Person. В частности, создадим один объект:
В итоге мы увидим на консоли:
Если необходимо, чтобы при создании объекта производилась какая-то логика, например, чтобы поля класса получали какие-то определенные значения, то можно определить в классе свои конструкторы. Например:
Теперь в классе определено три коструктора, каждый из которых принимает различное количество параметров и устанавливает значения полей класса.
Консольный вывод программы:
Ключевое слово this
Ключевое слово this представляет ссылку на текущий экземпляр класса. Через это ключевое слово мы можем обращаться к переменным, методам объекта, а также вызывать его конструкторы. Например:
В третьем конструкторе параметры называются так же, как и поля класса. И чтобы разграничить поля и параметры, применяется ключевое слово this:
Так, в данном случае указываем, что значение параметра name присваивается полю name.
Кроме того, у нас три конструктора, которые выполняют идентичные действия: устанавливают поля name и age. Чтобы избежать повторов, с помощью this можно вызвать один из конструкторов класса и передать для его параметров необходимые значения:
В итоге результат программы будет тот же, что и в предыдущем примере.
Инициализаторы
Кроме конструктора начальную инициализацию объекта вполне можно было проводить с помощью инициализатора объекта. Инициализатор выполняется до любого конструктора. То есть в инициализатор мы можем поместить код, общий для всех конструкторов:
Конструкторы в Java. Правила и особенности.
Как известно, объект является экземпляром определенного класса. Для его создания используется ключевое слово new, например:
Person student = new Person(“Mike”)
Этим кодом создается новый объект Person и указывается его имя – Mike. Строка «Mike» передается аргументом соответствующему конструктору Person:
Этот конструктор позволяет указать имя человека при создании объекта.
Конструктор всегда вызывается, когда создается новый экземпляр класса. Другими словами, конструкторы используются для инициализации состояния объекта при создании объекта. Конструкторы выглядят как обычные методы, но это далеко не так:
Ниже представлен набор из 7 основных правил работы с конструкторами, позволяющие полностью разобраться в их работе.
Это означает, что класс может иметь множество различных конструкторов, если их списки параметров различны. Например:
Имея три различных конструктора Rectangle можно создавать новый объект тремя различными способами:
Объявление конструкторов вовсе не обязательно. В случае если не определен ни один из конструкторов, то компилятор Java автоматически генерирует конструктор по умолчанию, который пуст и не имеет параметров.
Например, если мы напишем класс Rectangle следующим образом:
То компилятор автоматически вставляет конструктор по умолчанию: ectangle()
Рассмотрим следующий пример:
При попытке создать новый объект: Rectangle rect1 = new Rectangle(); Компилятор выдаст ошибку, потому что не может найти конструктор без аргументов.
В отличие от методов, конструкторы не наследуются. Пример:
Нельзя сделать что-то вроде этого: Square box = new Square(10, 10);
Можно сделать конструктор приватным, чтобы не дать внешнему коду создать новый экземпляр класса. В чем же может быть преимущество приватного конструктора?
В шаблоне проектирования, называемом Singleton, приватный конструктор используется, чтобы гарантировать, что всегда существует только один экземпляр класса. Класс Singleton предоставляет статический метод для получения этого уникального экземпляра.
При написании следующего класса: public class Person
Компилятор при вставке конструктора по умолчанию, укажет и необходимый модификатор доступа: public Preson();
Если это не так, то компилятор автоматически допишет вызов конструктора суперкласса без аргументов super(); Это может привести к ошибке, поскольку такого конструктора может не быть в суперклассе. Пример:
Приведет к ошибке, потому что компилятор вставляет вызов super () в конструкторе класса Child:
Однако компилятор не будет вставлять конструктор по умолчанию для класса Parent, т.к. уже есть другие конструкторы.
















