Как вызвать конструктор из конструктора java
Если в классе есть два конструктора, один из которых принимает параметры, а другой нет, то второй может вызвать первый с помощью ключевого слова this .
Кроме того из конструктора мы можем вызвать конструктор родительского класса с помощью ключевого слова super .
public class App public static void main(String[] args) class ClassX int x; public ClassX() // Конструктор без параметров this(0); // Вызов конструктора с параметрами > public ClassX(int xValue) x = xValue; > > class ClassXY extends ClassX int y; public ClassXY(int xValue, int yValue) super(xValue); // вызов родительского конструктора y = yValue; > > ClassX classX = new ClassX(); System.out.println(classX.x); // => 0 ClassXY classXY = new ClassXY(1, 2); System.out.println(classXY.x + classXY.y); // => 3 > >
Вызов конструктора из конструктора
Не могу понять, как это сделать, помогите кто знает. Знаю что элементарно, но все же: есть два конструктора, один конструктор (без аргументов) должен вызывать второй конструктор (с аргументом типа int ).
public class MyInitTest < private String a; private double c; < a = "non-static initialization block "; System.out.println(a); > < c = 20.03652; System.out.println(c + a); >static private String string; static private int anInt; static < string = "Static block"; System.out.println(string); >static < anInt = 6; System.out.println(anInt + "Static block"); >public MyInitTest() < >public MyInitTest(int) < >>
Отслеживать
34.4k 15 15 золотых знаков 65 65 серебряных знаков 94 94 бронзовых знака
Конструктор
Конструктор — это специальный метод, который вызывается при создании нового объекта. Не всегда удобно инициализировать все переменные класса при создании его экземпляра. Иногда проще, чтобы какие-то значения были бы созданы по умолчанию при создании объекта. По сути конструктор нужен для автоматической инициализации переменных.
Конструктор инициализирует объект непосредственно во время создания. Имя конструктора совпадает с именем класса, включая регистр, а по синтаксису конструктор похож на метод без возвращаемого значения.
private int Cat(); // так выглядит метод по имени Cat Cat(); // так выглядит конструктор класса Cat
В отличие от метода, конструктор никогда ничего не возвращает.
Конструктор определяет действия, выполняемые при создании объекта класса, и является важной частью класса. Как правило, программисты стараются явно указать конструктор. Если явного конструктора нет, то Java автоматически создаст его для использования по умолчанию. Когда мы реализовывали класс Box, то никакого конструктора не создавали.
Добавим в класс конструктор, который просто установит начальные значения для коробки.
class Box < int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки // Конструктор Box() < width = 10; height = 10; depth = 10; >// вычисляем объём коробки int getVolume() < return width * height * depth; >>
Мы временно удалили метод setDim() и добавили конструктор. Посмотрим, что получится:
Box catBox = new Box(); mInfoTextView.setText("Объём коробки: " + catBox.getVolume());
Программа выведет объём коробки, хотя мы не задавали никаких размеров для неё. Благодаря конструктору любая создаваемая коробка будет иметь какой-то зафиксированный объём.
Естественно, вы можете вернуть обратно метод setDim() (см. статью про классы) и установить свои размеры для коробки:
Box catBox = new Box(); // установим свои размеры для коробки catBox.setDim(10, 20, 30); mInfoTextView.setText("Объём коробки: " + catBox.getVolume());
Теперь вам должно быть ясно, что когда после ключевого слова new мы пишем имя класса со скобками, то на самом деле мы вызываем конструктор класса.
Возникает вопрос — но ведь сначала при создании класса мы не создавали конструктор, однако код new Box() работал. Дело в том, что если конструктор не определён явно, то Java создаст конструктор, который будет использоваться по умолчанию. В этом случае он просто присвоит всем переменным нулевые значения. Если вы создали сами конструктор, то конструктор по умолчанию использоваться не будет.
Подобно любому методу, у конструктора могут быть аргументы. В аргументах конструктора передаются параметры для инициализации объекта. Например, если у класса Cat имеется конструктор, который получает в качестве аргумента целое число, обозначающее возраст кота, то объекты Cat будут создаваться следующим образом:
Cat cat = new Cat(8); // коту 8 лет
Если Cat(int) является единственным конструктором класса, то компилятор не позволит создавать объекты Cat каким-либо другим способом.
Однако вернёмся к коробкам для котов. Созданный нами конструктор не особо полезен, так как создаёт одинаковые коробки. Создадим конструктор с параметрами в классе Box и закомментируйте первый конструктор без параметров:
// Второй конструктор Box(int w, int h, int d)
Если класс содержит один конструктор с параметрами, то вам придётся обязательно указать значения при объявлении класса:
// Это конструктор теперь не допустим // Box catBox = new Box(); // В конструкторе нужно указать значения размеров коробки Box catBox = new Box(100, 200, 100); mInfoTextView.setText("Объём коробки: " + catBox.getVolume());
Кстати, с таким конструктором метод setDim() нам уже не нужен. Мы можем задать размеры коробки сразу в конструкторе. Так как скорее всего коробка постоянна и не меняет своих размеров, то метод, пожалуй, лишний. Но если мы будем менять размеры коробки, то метод придётся оставить.
Класс может иметь несколько конструкторов. Снимите комментарий с первого конструктора и создайте две коробки — коробку по умолчанию и большую коробку.
Box defaultBox = new Box(); mInfoTextView.setText("Объём стандартной коробки: " + defaultBox.getVolume()); Box bigBox = new Box(100, 200, 200); mInfoTextView.append("\nОбъём большой коробки: " + bigBox.getVolume());
То есть, мы видим, что конструкторы поддерживают перегрузку, как и методы.
Например, мы можем создать ещё один конструктор специально для коробки в виде куба, где все стороны равны:
// Третий конструктор для куба Box(int len)
Вычисляем размер куба:
Box cube = new Box(5); int vol = cube.getVolume(); mInfoTextView.setText("Объём куба: " + vol);
Используем объект в качестве параметров
Мы пока использовали в качестве параметров в конструкторах простые типы. Но можно передать и объект самого класса. Добавим ещё один конструктор:
// Используем объект типа Box Box(Box ob)
В коде программы можно воспользоваться конструктором следующим образом:
Box box1 = new Box(100, 200, 100); Box cloneBox = new Box(box1); int vol = cloneBox.getVolume(); mInfoTextView.setText("Объём коробки: " + vol);
Класс Box (исходник)
package ru.alexanderklimov.box; class Box < int width; // ширина коробки int height; // высота коробки int depth; // глубина коробки // Конструктор Box() < width = 10; height = 10; depth = 10; >// Второй конструктор Box(int w, int h, int d) < width = w; height = h; depth = d; >// Третий конструктор для куба Box(int len) < width = height = depth = len; >// Используем объект типа Box Box(Box ob) < width = ob.width; height = ob.height; depth = ob.depth; >// вычисляем объём коробки int getVolume() < return width * height * depth; >// устанавливаем размеры коробки void setDim(int w, int h, int d) < width = w; height = h; depth = d; >>
Вызов перегруженных конструкторов через this()
Имея дело с перегруженными конструкторами, удобно один конструктор вызывать из другого через ключевое слово this. При выполнении конструктора this() сначала выполняется перегруженный конструктор, который соответствует списку параметров. Затем выполняются операторы, находящиеся внутри исходного конструктора, если таковые существуют. Вызов конструктора this() должен быть первым оператором в конструкторе.
Для начала создадим класс, который не использует конструктор this(), чтобы понять разницу.
class Cat < int age; int birthday; // Инициализируем переменные явно Cat(int i, int j) < age = i; birthday = j; >// Инициализируем переменные одним и тем значением Cat(int i) < age = i; birthday = i; >// Присвоим значения по умолчанию 0 Cat() < age = 0; birthday = 0; >>
Мы создали класс с тремя конструкторами. Перепишем класс, используя конструктор this().
class Cat < int age; int birthday; // Инициализируем переменные явно Cat(int i, int j) < age = i; birthday = j; >// Инициализируем переменные одним и тем значением Cat(int i) < this(i, i); // вызывается Cat(i, i); >// Присвоим значения по умолчанию 0 Cat() < this(0); // вызывается Cat(0); >>
У нас теперь только один конструктор, который присваивает значения полям — Cat(int, int). Что происходит при выполнении оператора:
Cat cat = new Cat(8);
Вызов конструктора Cat(8) приводит к выполнению конструктора this(8, 8), что равнозначно вызову конструктора Cat(8, 8).
Что происходит при выполнении оператора:
Cat cat2 = new Cat();
В этом случае вызывается конструктор this(0), что приводит к выполнению конструктора Cat(0), поскольку именно эта версия конструктора подходит по списку параметров. При этом конструктор Cat(0) по сути вызывает конструктор Cat(0, 0).
Использование перегруженных конструкторов через конструктор this() позволяет исключить дублирование кода, уменьшая время загрузки классов.
Но следует быть осторожным, так как конструкторы, которые вызывают конструктор this(), выполняются немного медленнее.
Закрытый конструктор
Иногда класс создаётся только для хранения каких-то статических полей и статических методов. Таким классам принято давать имена Utils, но это не обязательно. Такому классу не нужен конструктор, но если автор класса его не создал, то система сама создаст конструктор по умолчанию. Такой конструктор не имеет смысла, а также может послужить источником ошибок. Чтобы предохраниться от подобной проблемы вы сами явно должны создать пустрой конструктор и сделать его закрытым.
public class Utils < private Utils() < throw new AssertionError(); >. //ваш правильный код // Неправильный код, только для демонстрации! public static void someMethod() < Utils utils = new Utils(); utils.toString(); >>
Строка throw new AssertionError() не является обязательной, но она поможет выявить ошибку, если вы вызовете конструктор в самом классе. Компилятор пропустит такой вариант, но программа завершится с ошибкой.
Utils.someMethod(); // программа закроется с ошибкой
Подкласс для данного класса вы создать не сможете.
Вызов одного конструктора из другого

ООП невозможно без объектов, и это именно то, что составляет суть классов. На самом простом уровне класс — это тип данных. Но в отличие от примитивных типов, таких как целое число, число с плавающей точкой и символ, класс представляет собой сложный, определенный пользователем тип. Класс аналогичен записи в базе данных — в том смысле, что он инкапсулирует характеристики объекта. Например, запись типа Personможет содержать дату рождения, адрес, фамилию и номер телефона. Класс — это тип, составленный из других типов, которые в совокупности описывают объект.
Класс может представлять собой как бы заготовку, в которой часть методов реализована, а часть — нет. В этом случае в описании класса перед словом class должен стоять описатель abstact и при описании нереализованных методов тоже должен использоваться этот описатель.
public abstract class D
public abstract void g2(String str);
В классе D метод g1 — это обычный метод, g2 — абстрактный, он содержит только заголовок, но не содержит реализации.
Как видно из примера, тело абстрактного метода отсутствует, сразу после заголовка метода стоит точка с запятой.
Абстрактный класс не может использоваться непосредственно для порождения объектов. Для этого необходимо, используя этот класс как базовый, породить другой класс, в котором нужно определить все абстрактные методы. Тогда можно будет создавать объекты.
С другой стороны не запрещено описывать переменные абстрактного класса. Просто им нужно присваивать ссылки на объекты неабстрактных классов.
- В этой ситуации всегда применяется upcasting.
Возвращаясь к примеру с печатными изданиями, можно отметить, что класс Issue можно было бы реализовать как абстрактный, определив но не реализовав в нем метод print(…). Тогда во всех порожденных классах (Book, Journal, Newspaper) пришлось бы реализовать метод print(…). Фрагмент, печатающий каталог, при этом остался бы прежним.
Объект -Сущность в адресном пространстве вычислительной системы, появляющаяся при создании экземпляра класса или копирования прототипа (например, после запуска результатов компиляции и связывания исходного кода на выполнение).
Все объекты в Java создаются только явно, для чего используется операция new.
Одним из самых важных понятий объектно-ориентированного программирования является понятие объект. Объект есть экземпляр класса, в некоторых специальных случаях он может быть экземпляром нескольких классов (на этом остановимся ниже). Объект обладает набором состояний, в которых он может находиться, строго определенным поведением и уникальным идентификатором; структура и поведение схожих объектов определяется в их общем классе.
Объекты могут исполнять определенные роли. Роль определяет отношение между классом и его экземплярами [4], выделяя определенное их подмножество. Считается, что все эти объекты похожи по своему поведению и состояниям, которые они могут принимать. Например, в системе может существовать много объектов класса Абонент, но часть из них в данный момент играет роль вызываемых, часть — вызывающих, а остальные свободны. Таким образом у этого класса мы выделили три роли.
Таким образом, в UML существует два понятия роли: роль у партнеров ассоциации и роль, которую могут исполнять объекты. В дальнейшем во избежание путаницы будем называть роль, исполняемую объектом, объектом-ролью.
Фактически, объект-роль — это некоторый промежуточный уровень абстракции между объектами и классами. Например, рассмотрим класс человек: экземпляром этого класса является конкретный человек с именем и фамилией (его уникальным идентификатором) — Иванов Иван Петрович. У этого экземпляра могут быть состояния, например, болен, здоров, спит и т.п. В качестве объекта-роли можно привести роли: сын, жена, муж. Таким образом, объект-экземпляр класса может исполнять разные роли, например роли мужа и сына.
У объекта и объекта-роли есть уникальный идентификатор и строго определенные значения атрибутов.
На диаграмме объект и объект-роль представляется как прямоугольник с двумя отделениями. Верхнее отделение содержит имя объекта и имя его класса, по следующему синтаксису:
Описание методов класса
В первом приближении методы класса (class methods) можно рассматривать как функции.
Описание метода выглядит следующим образом
Здесь— это один из базовых типов (см. таблицу выше) или пользовательский тип (т.е. некоторое имя класса).— это список, возможно пустой, параметров метода.— собственно программный код данного метода.
Каждый аргумент или параметр метода в данном описании — это пара. Аргументы отделяются друг от друга запятыми.
Описания методов расположены внутри класса, на том же уровне вложенности скобок, что и описание полей класса. Не может быть описания метода вне класса или внутри другого метода или блока.
Вызов методов отличается от вызовов функций в не объектно-ориентированных языках программирования. При вызове обычного (не статического) метода класса обязательно должен быть указан объект этого класса и метод вызывается для этого объекта. Т.е. вызов метода — это вызов метода объекта.
Формальное исключение составляет вызов метода класса из другого (или того же) метода данного класса, в этом случае объект можно не указывать. Но фактически объект и в данном случае имеется, это — тот объект, для которого был вызван вызывающий метод.
Рассмотрим это на примерах. Опишем класс SomeClass и в нем методы f и g.
Здесь описан метод f с одним параметром целого типа, возвращающий целое значение и метод g без параметров, не возвращающий никакого значения. Приведем примеры вызова этих методов из некоторого фрагмента программы.
В приведенном фрагменте фигурируют переменные (или поля класса) a, x, b и v. Переменные a и b должны быть описаны как ссылки с типомSomeClass, переменные x и v должны быть целочисленными.
Данный фрагмент демонстрирует, что объект, для которого вызывается метод, должен быть указан при помощи ссылки, имя которой записывается перед именем метода через точку.
При вызове метода класса из метода того же класса объект указывать не обязательно. Это, как указано выше, не нарушает того правила, что при вызове метода всегда должен быть определен объект, для которого этот метод вызывается. Просто в данном случае этот объект уже определен при вызове вызывающего метода и для него же вызывается вызываемый метод.
Интерфейс — это класс без полей и без реализации, включающий только заголовки методов. Если некий класс наследует (или, как говорят, реализует) интерфейс, он должен реализовать все входящие в него методы. Использование интерфейсов предоставляет относительно дешёвую альтернативу множественному наследованию.
Мы уже познакомились с понятием класса в Java. Мы определили, что класс является как бы шаблоном для создания объектов класса (экземпляров класса) и что класс состоит из полей и методов класса. Но мы еще не рассмотрели очень важную составляющую классов — конструкторы класса .
Конструктор класса — это специальный метод класса. Он вызывается при создании объекта класса. Конструкторы (в своем описании) отличаются от других методов класса тем, что их имя совпадает с именем класса. Кроме того, при описании любого метода класса, кроме конструктора, мы обязаны указать тип возвращаемого значения, а если метод не возвращает никакого значение, то мы должны вместо типа явно указать void. При описании конструктора тип возвращаемого значения вообще не указывается.
Разберем более подробно, что происходит при создании объекта класса.
- Ищется класс объекта среди уже используемых в программе классов. Если его нет, то он ищется во всех доступных программе каталогах и библиотеках. После обнаружения класса в каталоге или библиотеке выполняется создание и инициализация статических полей класса. Т.е. для каждого класса статические поля инициализируются только один раз.
- Выделяется память под объект.
- Выполняется инициализация полей класса.
- Отрабатывает конструктор класса.
Это не полная схема, а упрощенная.
Итак, что такое конструктор .
- 1. Это специальный метод класса.
- 2. Его имя совпадает с именем класса.
- 3. Конструктор не возвращает никакого значения.
- 4. Конструктор, как и любой другой метод, может иметь параметры.
- 5. Конструктор без параметров называется конструктором по умолчанию (default constructor).
- 6. В классе может быть несколько конструкторов. В этом случае они должны иметь разные наборы параметров.
- 7. Если в классе нет ни одного конструктора, то генерируется пустой конструктор по умолчанию. Если в классе есть хотя бы один конструктор, то конструктор по умолчанию не генерируется.
До сих пор в примерах мы использовали примерно следующий синтаксис создания объектов.
SomeClass obj = new SomeClass();
В данном случае создается объект и при его создании используется конструктор без параметров (конструктор по умолчанию). Но возможен и другой вариант.
SomeClass obj = new SomeClass(1, ‘a’);
Здесь при создании объекта вызывается конструктор с двумя параметрами. Т.е. в классе SomeClass должен быть описан конструктор, имеющий один арифметический параметр (например, int) и один символьный параметр.
Для того чтобы обе вышеприведенные строки были корректными, описание класса SomeClass должно выглядеть примерно так.
Вызов одного конструктора из другого
В Java есть одна удобная возможность, позволяющая сократить суммарный объем кода конструкторов. Обычно все конструкторы класса имеют общую часть кода, поскольку они должны выполнять одинаковые действия, которые отличаются только некоторыми деталями. Можно вынести эту общую часть кода в отдельный метод и вызывать его из всех конструкторов. Но есть и другая возможность. В Java можно вызвать один конструктор из другого. Для этого используется ключевое слово this . Рассмотрим это на примере.
В классе Point (точка) имеется два конструктора. Один, более общий, с двумя параметрами, предназначен для конструирования точки плоскости с заданными координатами. Другой, без параметров, строит точку с координатами (0, 0). В нем для экономии кода просто вызывается первый из конструкторов с параметрами (0, 0).
Есть одно ограничение на вызов одного конструктора из другого. Такой вызов должен быть первым оператором в вызывающем конструкторе.
Работа со строками (класс String)
Первый стандартный класс Java, который мы рассмотрим — это класс String. Этот класс определен в стандартной библиотеке Java. Он используется для работы со строками.
Откроем документацию по классу String. Во-первых, обратим внимание на конструкторы класса. В документации конструкторы класса описываются сразу после описания полей класса. Конструкторы класса String предоставляют широкие возможности конструирования строк.
public String() Создает пустую строку
public String(char[] value) Создает строку из массива символов.
public String(byte[] bytes) Создает строку из массива байт, преобразуя байты в символы в соответствии с кодировкой по умолчанию.
Есть и другие конструкторы класса String.
В силу важности строк в Java для класса String существуют расширенные возможности языка. По общим правилам создания объектов мы должны были бы при построении строки писать так
String str = new String(какая-то строка);
Такая запись допустима, но существует ее упрощенный вариант:
String str = какая-то строка;
Для строк определена операция сложения, которая означает конкатенацию (сцепление) строк. Определена операция сложения строки с числом. При этом сначала число преобразуется в строку, а потом выполняется конкатенация полученных строк.
Также определена операция сложения строки с любым объектом. Она выполняется так. Сначала для этого объекта вызывается метод toString(), потом выполняется конкатенация полученных строк. Метод toString() есть у всех объектов Java (рассмотрим подробнее при изучении наследования).
Примеры сложения строк с числами нам уже встречались — в операторах типа
Вернемся к документации по классу String. Следует обратить внимание на следующие методы этого класса.
public char charAt(int index) Выбирает из строки символ с индексом index (символы индексируются от нуля).
public int compareTo(String anotherString) Сравнивает строку с другой строкой
public int indexOf(int ch) Ищет символ в строке
public int indexOf(String str) Ищет указанную параметром строку в данной
public int length() Возвращает длину строки
public String substring(int beginIndex, int endIndex) Выделяет подстроку из строки
public String trim() Удаляет из строки начальные и концевые пробелы
Набор методов valueOf(…) позволяет переводить значения различных типов в строки.
Модификаторы доступа уточняют модель объекта, контролируя, как именно его можно использовать. Проще говоря, модификаторы доступа определяют, что можно, а чего нельзя делать с объектом. Чтобы разобраться в этом, обратимся к примеру из процедурного программирования.
Назовем подпрограммой функцию, которая никогда не вызывается напрямую, а лишь из других функций. Предположим, что вы пишете библиотеку функций и подпрограмм, используемую несколькими другими программистами. В этом случае была бы полезна возможность помечать подпрограммы как вспомогательные функции, чтобы оградить пользователей от потенциально неправильного применения библиотеки, но добиться этого можно только путем документирования. В ООП же модификаторы доступа не просто обозначают степень важности функций, но и препятствуют их вызову из внешней программы. Тем самым реализуется языковое ограничение, запрещающее вызывать подпрограммы напрямую. Правильно спроектированные классы оказываются самодокументированными и самоконтролируемыми. Модификаторы доступа существуют по той же причине — чтобы облегчить повторное использование.
Пакет — это вместилище для некоторого набора классов и других пакетов. Пакет является самостоятельным пространством имен.
Отметим, что пакет физически содержит сущности, определенные в нем (говорят, что сущности принадлежат пакету). Это означает, что если будет уничтожен пакет, то будут уничтожено и все его содержимое.
При описании классов пакета нередко бывает полезно сослаться на класс, определенный в другом пакете. Это можно сделать, импортировав нужный пакет. Это означает, что в импортирующем пакете станут доступными все классы импортируемого пакета. При этом пространства имен не объединятся: для использования класса надо будет указать его имя с полным путем пакета, в котором он лежит.
Обычно физически библиотека — это jar-файл (rt.jar, например). Но свою личную библиотеку можно сделать и просто в каком-либо каталоге. Кроме того, библиотека может быть zip-файлом.
Но библиотека является довольно крупным хранилищем классов. На практике требуется какой-то дополнительный механизм разбиения всего множества классов, хранящихся в библиотеке на отдельные части. В Java таким механизмом являются пакеты.
Пока познакомимся с использованием пакетов из стандартной библиотеки Java. Лучше всего обратиться к документации по API Java. Полный список пакетов стандартной библиотеки Java:
Нужно разобраться с именами пакетов. Как видно, имя составное, разделенное точками. Это связано с общепринятым в Java принципом построения имен пакетов. Этот принцип состоит в том, что в имени пакета присутствует Internet-адрес разработчика пакета в обратном порядке. На примере:
Пусть Ваш адрес petr@provider.da . Тогда все имена пакетов Ваших приложений должны начинаться с da.provider.petr.. Так, для пакета, содержащего вспомогательные сервисные классы подойдет имя da.provider.petr.util.
Кроме того, с именем пакета связана структура каталогов, в которых должны размещаться классы. Это будет рассмотрено подробнее позже, когда будем рассматривать создание собственных пакетов.
Статьи к прочтению:
- Визуализация нескольких графиков.
- Визуальное событийно-управляемое программирование
Java уроки для начинающих, часть 12 — Работа с методами
Похожие статьи:
- Который в данном случае преобразуется в вызов конструктора xycoord (0 , 0) . то же самое происходит и при создании объекта t2. Вызывать перегружаемый конструктор с помощью ключевого слова this полезно, в частности, потому, что он позволяет исключить ненужное дублирование кода. В…
- Вызов одного bat файла из другого Здесь нам может помочь команда CALL: CALL [диск:][путь]имя_файла [параметры_вызова] параметры_вызова Параметры командной строки, использующиеся при…