Метод конструктор языка java

Конструкторы классов. Java JDK 1.5

Java-университет

Конструктор имеется в любом классе. Даже если вы его не написали, компилятор Java сам создаст конструктор по умолчанию (default constructor). Этот конструктор пустой и не делает ничего, кроме вызова конструктора суперкласса. Т.е. если написать:

В данном случае явно класса предка не указано, а по умолчанию все классы Java наследуют класс Object поэтому вызывается конструктор класса Object . Если в классе определен конструктор с параметрами, а перегруженного конструктора без параметров нет, то вызов конструктора без параметров является ошибкой. Тем не менее, в Java, начиная с версии 1.5, можно использовать конструкторы с аргументами переменной длины. И если есть конструктор, имеющий аргумент переменной длины, то вызов конструктора по умолчанию ошибкой не будет. Не будет потому, что аргумент переменной длины может быть пустым. Например, следующий пример не будет компилироваться, однако если раскомментарить конструктор с аргументом переменной длины, то компиляция и запуск пройдут успешно и в результате работы строки кода DefaultDemo dd = new DefaultDemo() ; вызовется конструктор DefaultDemo(int . v) . Естественно, что в данном случае необходимо пользоваться JSDK 1.5. Файл DefaultDemo.java

 class DefaultDemo < DefaultDemo(String s) < System.out.print("DefaultDemo(String)"); >/* DefaultDemo(int . v) < System.out.println("DefaultDemo(int . )"); >*/ public static void main(String args[]) < DefaultDemo dd = new DefaultDemo(); >> 

Однако, в распространенном случае, когда в классе вообще не определено ни одного конструктора, вызов конструктора по умолчанию (без параметров) будет обязательным явлением, поскольку подстановка конструктора по умолчанию происходит автоматически.

Создание объекта и конструкторы

  • Ищется класс объекта среди уже используемых в программе классов. Если его нет, то он ищется во всех доступных программе каталогах и библиотеках. После обнаружения класса в каталоге или библиотеке выполняется создание, и инициализация статических полей класса. Т.е. для каждого класса статические поля инициализируются только один раз.
  • Выделяется память под объект.
  • Выполняется инициализация полей класса.
  • Отрабатывает конструктор класса.
  • Формируется ссылка на созданный и инициализированный объект. Эта ссылка и является значением выражения, создающего объект. Объект может быть создан и с помощью вызова метода newInstance() класса java.lang.Class . В этом случае используется конструктор без списка параметров.

Перегрузка конструкторов

Конструкторы одного класса могут иметь одинаковое имя и различную сигнатуру. Такое свойство называется совмещением или перегрузкой(overloading). Если класс имеет несколько конструкторов, то присутствует перегрузка конструкторов.

Параметризированные конструкторы

Сигнатура конструктора – это количество и типы параметров, а также последовательность их типов в списке параметров конструктора. Тип возвращаемого результата не учитывается. Конструктор не возвращает никаких параметров. Это положение объясняет в некотором смысле, как Java различает перегруженные конструкторы или методы. Java различает перегруженные методы не по возвращаемому типу, а по числу, типам и последовательности типов входных параметров. Конструктор не может возвращать даже тип void , иначе он превратится в обычный метод, даже не смотря на сходство с именем класса. Следующий пример демонстрирует это. Файл VoidDemo.java

 class VoidDemo < /** * Это конструктор */ VoidDemo() < System.out.println("Constructor"); >/** * А это уже обычный метод, даже не смотря на сходство с * именем класса, поскольку имеется возвращаемый тип void */ void VoidDemo() < System.out.println("Method"); >public static void main(String s[]) < VoidDemo m = new VoidDemo(); >> 

Это лишний раз доказывает, что конструктором является метод без возвращаемых параметров. Тем не менее, для конструктора можно задать один из трех модификаторов public , private или protected . И пример теперь будет выглядеть следующим образом: Файл VoidDemo2.java

 class VoidDemo2 < /** * Это конструктор */ public VoidDemo2() < System.out.println("Constructor"); >/** * А это уже обычный метод, даже не смотря на сходство с * именем класса, поскольку имеется возвращаемый тип void */ private void VoidDemo2() < System.out.println("Method"); >public static void main(String s[]) < VoidDemo2 m = new VoidDemo2(); >> 

В конструкторе разрешается записывать оператор return , но только пустой, без всякого возвращаемого значения. Файл ReturnDemo.java

 class ReturnDemo < /** * В конструкторе допускается использование оператора * return без параметров. */ public ReturnDemo() < System.out.println("Constructor"); return; >public static void main(String s[]) < ReturnDemo r = new ReturnDemo(); >> 

Конструкторы, параметризированные аргументами переменной длины

В Java SDK 1.5 появился долгожданный инструмент – аргументы переменной длины для конструкторов и методов(variable-length arguments). До этого переменное количество документов обрабатывалось двумя неудобными способами. Первый из них был рассчитан на то, что максимальное число аргументов ограничено небольшим количеством и заранее известно. В таком случае можно было создавать перегружаемые версии метода, по одной на каждый вариант списка передаваемых в метод аргументов. Второй способ рассчитан на неизвестное заранее и большое количество аргументов. В этом случае аргументы помещались в массив, и этот массив передавался методу. Аргументы переменной длины чаще всего задействованы в последующих манипуляциях с инициализациями переменных. Отсутствие некоторых из ожидаемых аргументов конструктора или метода удобно заменять значениями по умолчанию. Аргумент переменной длины есть массив, и обрабатывается как массив. Например, конструктор для класса Checking с переменным числом аргументов будет выглядеть так:

Символьная комбинация . сообщает компилятору о том, что будет использоваться переменное число аргументов, и что эти аргументы будут храниться в массиве, значение ссылки на который содержится в переменной n. Конструктор может вызываться с разным числом аргументов, включая их полное отсутствие. Аргументы автоматически помещаются в массив и передаются через n. В случае отсутствия аргументов длина массива равна 0. В список параметров наряду с аргументами переменной длины могут быть включены и обязательные параметры. В этом случае параметр, содержащий переменное число аргументов должен обязательно быть последним в списке параметров. Например:

Читайте также:  Python module file location

Вполне очевидное ограничение касается количества параметров с переменной длиной. В списке параметров должен быть только один параметр переменной длины. При наличии двух параметров переменной длины компилятору невозможно определить, где заканчивается один параметр и начинается другой. Например:

Файл Checking.java Например, есть аппаратура, способная распознавать номера автомобилей и запоминать номера квадратов местности, где побывал каждый из автомобилей за день. Необходимо из общей массы зафиксированных автомобилей отобрать те, которые в течение дня побывали в двух заданных квадратах, скажем 22 и 15, согласно карте местности. Вполне естественно, что автомобиль может в течение дня побывать во многих квадратах, а может только в одном. Очевидно, что количество посещенных квадратов ограничено физической скоростью автомобиля. Составим небольшую программу, где конструктор класса будет принимать в качестве аргументов номер автомобиля как обязательный параметр и номера посещенных квадратов местности, число которых может быть переменным. Конструктор будет проверять, не появился ли автомобиль в двух квадратах, если появился, то вывести его номер на экран.

Передача параметров в конструктор

  • основные типы (примитивы);
  • ссылки на объекты.
  • конструктор не может менять значения входных параметров основных (примитивных) типов;
  • конструктор не может изменять ссылки входных параметров;
  • конструктор не может переназначать ссылки входных параметров на новые объекты.
  • изменять состояние объекта, передаваемого в качестве входного параметра.
 class Employee < Employee(String x, String y) < String temp = x; x = y; y = temp; >public static void main(String args[]) < String name1 = new String("Alice"); String name2 = new String("Mary"); Employee a = new Employee(name1, name2); System.out.println("name1="+name1); System.out.println("name2 x="+x); >public static void main(String args[]) < int value = 1000; Salary1 s1 = new Salary1(value); System.out.println("value s1.value=" +s1.value); System.out.println("s2.value d First object creation: "+s1.value); Salary3 s2 = new Salary3(s1); System.out.println("Second object creation: "+s2.value); System.out.println("What's happend with first object?:"+s1.value); Salary3 s3 = new Salary3(s1); System.out.println("Third object creation: "+s3.value); System.out.println("What's happend with first object?:"+s1.value); >> 
 First object creation: 1000 Second object creation: 1000 What's happend with first object?: 3000 Third object creation: 1000 What's happend with first object?: 9000 

Сначала с помощью строчки Salary3 s1 = new Salary3() ; создается новый объект. Далее, если бы с помощью строки Salary3 s2 = new Salary3(s1) ; или строки Salary3 s3 = new Salary3(s1) ; можно было бы создать ссылку на уже существующий объект, то s1.value s2.value и s3.value хранили бы одинаковое значение 1000 . На самом деле в строке Salary3 s2 = new Salary3(s1) ; создастся новый объект для переменной s2 и изменится состояние объекта для переменной s1 , через передачу своего значения ссылки на объект, в параметре конструктора. В этом можно убедиться по результатам вывода. А при выполнении строки Salary3 s3 = new Salary3(s1) ; создастся НОВЫЙ объект для переменной s3 и снова изменится состояние объекта для переменной s1 .

Читайте также:  Font size normal css

Конструкторы и блоки инициализации, последовательность действий при вызове конструктора

  1. Все поля данных инициализируются своими значениями, предусмотренными по умолчанию (0, false или null).
  2. Инициализаторы всех полей и блоки инициализации выполняются в порядке их перечисления в объявлении класса.
  3. Если в первой строке конструктора вызывается другой конструктор, то выполняется вызванный конструктор.
  4. Выполняется тело конструктора.
  • присвоить значение в объявлении;
  • присвоить значения в блоке инициализации;
  • задать его значение в конструкторе.
 class Initialization < int i; short z = 10; static int x; static float y; static < x = 2000; y = 3.141; >Initialization() < System.out.println("i="+i); System.out.println("z="+z); z = 20; System.out.println("z Hi"); >> public class SubClass extends Example

Класс SubClass автоматически наследует метод sayHi() определенный в родительском классе. В тоже время, конструктор Example() родительского класса не наследуется его потомком SubClass .

Ключевое слово this в конструкторах

Конструкторы используют this чтобы сослаться на другой конструктор в этом же классе, но с другим списком параметров. Если конструктор использует ключевое слово this , то оно должно быть в первой строке, игнорирование этого правила приведет к ошибке компилятора. Например: Файл ThisDemo.java

 public class ThisDemo < String name; ThisDemo(String s) < name = s; System.out.println(name); >ThisDemo() < this("John"); >public static void main(String args[]) < ThisDemo td1 = new ThisDemo("Mary"); ThisDemo td2 = new ThisDemo(); >> 

В данном примере имеется два конструктора. Первый получает строку-аргумент. Второй не получает никаких аргументов, он просто вызывает первый конструктор используя имя «John» по-умолчанию. Таким образом, можно с помощью конструкторов инициализировать значения полей явно и по умолчанию, что часто необходимо в программах.

Ключевое слово super в конструкторах

Конструкторы используют super , чтобы вызвать конструктор суперкласса. Если конструктор использует super , то этот вызов должен быть в первой строке, иначе компилятор выдаст ошибку. Ниже приведен пример: Файл SuperClassDemo.java

 public class SuperClassDemo < SuperClassDemo() < >> class Child extends SuperClassDemo < Child() < super(); >> 

В этом простом примере конструктор Child() содержит вызов super() , который создает экземпляр класса SuperClassDemo , в дополнение к классу Child . Так как super должен быть первым оператором, выполняемым в конструкторе подкласса, этот порядок всегда одинаков и не зависит от того, используется ли super() . Если он не используется, то сначала будет выполнен конструктор по умолчанию (без параметров) каждого суперкласса, начиная с базового класса. Следующая программа демонстрирует, когда выполняются конструкторы. Файл Call.java

 //Создать суперкласс A class A < A() < System.out.println("Inside A constructor."); >> //Создать подкласс B, расширяющий класс A class B extends A < B() < System.out.println("Inside B constructor."); >> //Создать класс (C), расширяющий класс В class C extends B < C() < System.out.println("Inside C constructor."); >> class Call < public static void main(String args[]) < C c = new C(); >> 
 Inside A constructor. Inside B constructor. Inside C constructor. 

Конструкторы вызываются в порядке подчиненности классов. В этом есть определенный смысл. Поскольку суперкласс не имеет никакого знания о каком-либо подклассе, то любая инициализация, которую ему нужно выполнить, является отдельной. По возможности она должна предшествовать любой инициализации, выполняемой подклассом. Поэтому-то она и должна выполняться первой.

Читайте также:  Chrome is blocking javascript

Настраиваемые конструкторы

Механизм идентификации типа во время выполнения является одним из мощных базовых принципов языка Java, который реализует полиморфизм. Однако такой механизм не страхует разработчика от несовместимого приведения типов в ряде случаев. Самый частый случай – манипулирование группой объектов, различные типы которых заранее неизвестны и определяются во время выполнения. Поскольку ошибки, связанные с несовместимостью типов могут проявиться только на этапе выполнения, то это затрудняет их поиск и ликвидацию. Введение настраиваемых типов в Java 2 5.0 частично отодвигает возникновение подобных ошибок с этапа выполнения на этап компиляции и обеспечивает недостающую типовую безопасность. Отпадает необходимость в явном приведении типов при переходе от типа Object к конкретному типу. Следует иметь ввиду, что средства настройки типов работают только с объектами и не распространяются на примитивные типы данных, которые лежат вне дерева наследования классов. Благодаря настраиваемым типам все приведения выполняются автоматически и скрыто. Это позволяет обезопасить от несоответствия типов и гораздо чаще повторно использовать код. Настраиваемые типы можно использовать в конструкторах. Конструкторы могут быть настраиваемыми, даже если их класс не является настраиваемым типом. Например:

 class GenConstructor < private double val; GenConstructor(T arg) < val = arg.doubleValue(); >void printValue() < System.out.println("val: "+val); >> class GenConstructorDemo < public static void main(String args[]) < GenConstructor gc1 = new GenConstructor(100); GenConstructor gc2 = new GenConstructor(123.5F); gc1.printValue(); gc2.printValue(); >> 

Поскольку конструктор GenConstructor задает параметр настраиваемого типа, который должен быть производным классом от класса Number , его можно вызвать с любы

Источник

Оцените статью