Конструкторы выполняют инициализацию объекта (устанавливают изначальное значение инстанса сразу же при его создании).
конструктор "медвежонок" инициализирует объект "медвежонок (побольше)"
byte 0
short 0
int 0
long 0L
float 0.0f
double 0.0d
char '\u0000'
String (or any object) null
boolean false
2) Конструктор без аргументов (no-args constructor)
Объявление переменной для хранения ссылки на создаваемый объект (чтобы можно было к нему обращаться, например, для вызова какого-то метода) выглядит следующим образом:
ТипПеременной имяПеременной = new ИмяКонструктора();
Объект создаётся при помощи оператора new, который динамически выделяет для него память в куче (heap) и возвращает на него ссылку, которая присваивается переменной.
Имя класса, идущее после оператора new, указывает на имя его конструктора, который определяет, что происходит при создании объекта (это может быть инициализация полей, вызов других конструкторов и т.д.).
3) Параметризованный конструктор (parameterized constructor)
Параметризированный конструктор принимает аргументы (чтобы иметь возможность передавать нужные начальные значения в объект).
Если конструкторов у класса несколько, то будет вызываться будет тот конструктор, который указывается при создании объекта набором параметров соответствующим используемому конструктору с таким же самым перечнем праметров.
Такие конструкторы применяются тогда, когда необходимо создать копию сложного объекта, но при этом мы не хотим использовать метод clone().
(Например, если в копии объекта какие-то поля должны отличаться).
Такой механизм характеризуется копированием ссылок оригинального объекта в создаваемый объект.
При поверхностном копировании копируются ссылки на значения из оригинального объекта. При этом, если копируемая ссылка принадлежит mutable-объекту (если переменная объекта будет ссылаться на изменяемую (mutable) переменную), то при ее изменении в любом объекте (не важно, в новом или исходном) ее значение изменится во всех других объектах. Т.е. изменения затрагивают все объекты.
Глубокое копирование (deep copy)
Этот вид копирования позволяет создавать объекты, которые будут содержать точные копии всех полей (в том числе ссылочных) оригинального объекта, но при этом будут абсолютно независимы от оригинального объекта.
Изменение полей скопированного (склонированного) объекта не отражается на изменении полей оригинального объекта (также и в обратном случае).
Связанные конструкторы
Не обязательно передавать в конструктор для инициализации всех полей класса какие-то значения. Часть обязанностей можно возложить на компилятор, который присвоит полям значения по умолчанию (если это не критично). Также, в процессе работы программы, можно использовать сеттеры.
Объект-значение (Value Objects)
Один из вариантов использования конструкторов в Java — создание объектов-значений.
Если мы используем ключевое слово final при определении членов класса. Это означает, что каждый из них может быть инициализирован только с помощью конструктора. Их нельзя переназначить позже в каком-либо другом методе. Мы можем считать эти значения, но не можем их изменить.
Если мы создадим несколько конструкторов для класса, то каждый из них должен будет инициализировать каждую финальную переменную. Невыполнение этого приведет к ошибке компиляции. Например, «java: variable amount might not have been initialized».
Класс может содержать любое количество конструкторов (NB! у них должны различаться их аргументы иначе выдаст ошибку). При большом
количестве конструкторов для упрощения кода можно использовать Шаблоны
проектирования из категории Creational Design Patterns.
Имя конструктора должно совпадать с именем класса, с учётом регистра.
Конструктор может принимать в качестве аргумента как примитивные типы данных, так и объекты
Значение примитивов (int, float, double и т. д.) копируются как есть
Ссылки на объекты типа immutable (например String), также копируются как есть. Несмотря на то, что оригинальный и порожденный объекты ссылаются на тот же самый адрес в памяти, immutable-объекты никогда не будут изменяться
Ссылки на mutable объекты (например Date, List и т. д.) должны копироваться при помощи глубокого копирования. Иначе оригинальный и порожденный объекты будут ссылаться на один и тот же адрес в памяти и соответственно, любые изменения объекта (оригинального или порожденного) будут отображаться на всех объектах
Конструктор не может быть объявлен как final, static, synchronized или abstract
Конструктор может быть перегружен (overload)
Перегрузка конструктора означает, что какой-либо класс может иметь множество конструкторов, но при этом их списки параметров должны отличаться между собой.
Конструкторы не наследуются подобно методам суперкласса
Конструкторы могут иметь модификатор доступа private, что не позволит создавать его экземпляры. Например, приватный конструктор может использоваться для контроля над количеством создаваемых экземпляров: всегда можно будет создать только один объект.
Иногда класс может быть служебным и хранить какие-то статические поля и статические методы. Необходимости в создании экземпляров таких классов нет, поэтому и в конструкторе нет смысла, но как мы уже знаем, компилятор создаст конструктор по умолчанию. Чтобы этого не произошло, мы можем сами создать пустой конструктор и сделать его закрытым, используя модификатор доступа private. Такой конструктор называется закрытый.
Метод namesConcatinate объединяет имя и фамилию в одну строковую переменную. Закрытый конструктор BankAcoountUtils() делает невозможным создание экземпляра класса BankAccountUtils. Следующий код выведет объединенную строковую переменную без создания объекта:
Конструктор по умолчанию имеет тот же самый модификатор доступа, что и класс
Конструктор класса вызывает конструктор по умолчанию его суперкласса (по цепочке вплоть до Object)
Компилятор Java автоматически вставляет неявно вызов super () в первую строку любого конструктора. Поэтому, обращайте внимание на это правило при наследовании родительского класса.
Первым выражением в конструкторе должен быть вызов метода this () или super()
Конструктор и сеттеры можно (нужно) использовать совместно:
Если используется конструктор по умолчанию, то далее предполагается, что при помощи сеттеров (setter) полям объекта присваиваются нужные нам значения, которые на момент его создания были неизвестны.
В случае же с параметризованным конструктором, значения полей сразу инициализируются подходящими нам значениями. Один вызов такого конструктора заменяет собой вызов нескольких сеттеров. При этом создается объект с корректными значениями полей. Кроме того, параметризованный конструктор позволяет создать неизменяемый объект (immutable — это объект, состояние которого не может быть изменено после создания), что невозможно при использовании сеттеров.
Также, возможны комбинации, когда объект создается с несколькими обязательными полями, и с полями, инициализированными значениями по умолчанию, которые в дальнейшем могут неоднократно изменяться сеттерами.
public class Tea {
String name;
int age;
//конструктор для класса Tea
public void setTea(String name, String sort) {
this.name = name;
this.sort = sort;
}
public static void main(String[] args) {
Tea cup = new Tea("Green", '"Japanese");
}
}
Также завершает заголовок конструктора throws-выражение, поскольку создать ошибку – это единственный способ для конструктора не создавать объект: если конструктор выполнился без ошибок, то объект гарантированно создается.
Но бывает и другая ситуация, когда мы хотим перед отработкой конструктора потомка вызвать конструктор суперкласса. В таком случае нужно использовать ключевое слово super().
Комментариев нет:
Отправить комментарий