Курс

"Программирование Java"

Конструкторы

Сравнение объектов

Кроме обычных методов классы могут определять специальные методы, которые называются конструкторами. Конструкторы вызываются при создании нового объекта данного класса. Конструкторы выполняют инициализацию объекта

Если в классе не определено ни одного конструктора, то для этого класса автоматически создается конструктор без параметров

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

public class Main{

    public static void main(String[] args) {

        User user1 = new User (); // создание объекта

        user1.displayInfo();

        // изменяем имя и возраст

        user1.name = "Alex";

        user1.age = 25;

        user1.displayInfo();

    }

}

class User {

    String name;    // имя

    int age;        // возраст

    void displayInfo(){

        System.out.printf("Name: %s \tAge: %d\n", name, age);

    }

}

 

После создания объекта мы можем обратиться к переменным объекта User

через переменную user1и установить или получить их значения, например, user1.name = "Alex".

В итоге мы увидим на консоли:

Name: null Age: 0

Name: Tom Age: 34

Как работаю конструкторы:

Когда мы вызываем конструкцию new User()оператор new выделяет память для объекта User. 

И затем вызывается конструктор по умолчанию, который не принимает никаких параметров. В итоге после выполнения данного выражения в памяти будет выделен участок, где будут храниться все данные объекта User.  А наша переменная получит ссылку на созданный объект.

Если конструктор не инициализирует значения полей объекта, то они получают значения по умолчанию. 

Для переменных числовых типов это число 0, а для типа string и классов - это значение null (то есть фактически отсутствие значения)

Если необходимо, чтобы при создании объекта производилась какая-то логика, например, чтобы поля класса получали какие-то определенные значения, то можно определить в классе свои конструкторы. 

 

Например:

public class Main{

      

    public static void main(String[] args) {

         

        User user1 = new User ();      // вызов конструктора без параметров

        user1.displayInfo();

      

    }

}

class User {

     

    String name;    // имя

    int age;        // возраст

   

    User () { // собственный конструктор

        name = "Undefined";

        age = 18;

    }

    void displayInfo(){

        System.out.printf("Name: %s \tAge: %d\n", name, age);

    }

}

 

В итоге мы увидим на консоли:

Name: Undefined Age: 18

Для того, чтобы при создании объекты имели разные значения полей необходимо использовать так называемые конструкторы с параметрами. Модифицируем наш код

В конструкторе добавим параметры, которые будем использовать для передачи данные объекту. При указании параметров не забываем про типы данных которое используются в полях класса.

public class Main{

      

    public static void main(String[] args) {

        User user1 = new User("Alex"); // вызов конструктора с параметром

        user1.displayInfo();

    }

}

class User {

     

    String name;    // имя

    int age;        // возраст

    User(String n) {

        name = n;

        age = 18;

    }

 

    void displayInfo(){

        System.out.printf("Name: %s \tAge: %d\n", name, age);

    }

}

 

Важное замечание: при создании объектов мы должны соблюдать порядок передаваемых данных и следить за тем, чтобы был правильный тип данных, в противном случае мы получим ошибку

 

Иногда возможны ситуации, когда мы при создании объектов не всегда можем передать все данные в конструктор, например, у человека может отсутствовать фамилия или телефон. Тогда в классе можно определить несколько конструкторов

Класс может иметь несколько конструкторов, если их сигнатура (параметры, которые они принимают) не совпадают. 

Когда класс содержит несколько конструкторов, мы говорим, что конструктор перегружен (поставляется в нескольких версиях)

public class Main{

    public static void main(String[] args) {

         

        User user1= new User();      // вызов первого конструктора без параметров

        user1.displayInfo();

         

        User user2= new User("Tom"); // вызов второго конструктора с одним параметром

        user2.displayInfo();

         

        User user3= new User("Sam", 25); // вызов третьего конструктора с двумя параметрами

        user3.displayInfo();

    }

}

class User {

     

    String name;    // имя

    int age;        // возраст

    User(){

        name = "Undefined";

        age = 18;

    }

    User(String n){

        name = n;

        age = 18;

    }

    User(String n, int a){

        name = n;

        age = a;

    }

    void displayInfo(){

        System.out.printf("Name: %s \tAge: %d\n", name, age);

    }

}

 

Вызов перегруженных конструкторов через this()

При определении перегруженных конструкторов зачастую для того, чтобы не дублировать код, также используют ключевое слово this

Это подход очень часто используется при создании копий объектов.

В Java объекты — это ссылочный тип, поэтому нельзя просто взять и присвоить другой переменной значение объекта т.к. передастся только ссылка.

User user5 = user1;

В данном случае user5 будет хранить ссылку на user1 т.е. по сути это будет один и тот же объект.

Для того чтобы правильно создать копию объекта нудно использовать конструктор копирования. Давайте создадим такой конструктор:

    public User(int id, String name) {

        this.id = id;

        this.name = name;

  }

 

 

 public User (User u) {

        this(u.getId(), u.getName());

 }

 

Клиентский код:

User u1 = new User(1, "Name 1");

User u2 = new User(u1);