JavaRush/Java блог/Архив info.javarush/Вызов конструктора из конструктора
alexnjc
31 уровень

Вызов конструктора из конструктора

Статья из группы Архив info.javarush
участников
Часто для того, чтобы избежать написание повторяющегося кода инициализации, необходимо вызвать код одного конструктора из другого.
Вызов конструктора из конструктора - 1
Вот пример, как это можно делать:
public class SomeClass {
  int a;
  int b;
  int c;

public SomeClass(int a, int b){
   this.a = a;
   this.b = b;
  }

public SomeClass(int a, int b, int c){
    // Вызов конструктора с двумя параметрами.
    this(a, b);
    this.c = c;
  }

public void show(){
    System.out.println("a = " + a);
    System.out.println("b = " + b);
    System.out.println("c = " + c);
  }
}
Как вы видите, для этого используется ключевое слово this, после которого в круглых скобках указываем параметры для соотвествующего конструктора (с двумя параметрами в данном случае). Вы можете вызвать один конструктор из другого в том же классе, или в надклассе, со следующими ограничениями:
  • Вызываемый конструктор должен быть в первой строке кода в вызывающем конструкторе.
  • Вложенный конструктор не может иметь никакой явной или неявной ссылки на "this". Таким образом, вы не можете попасть во внутренний класс.
Комментарии (40)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
milyasow
Уровень 34
13 февраля 2022, 00:03
Вижу, многие ломают себе мозг, пытаясь понять, что же значит загадочная фраза Вложенный конструктор не может иметь никакой явной или неявной ссылки на "this". Таким образом, вы не можете попасть во внутренний класс. А это на самом деле просто кастрированный перевод одного из ответов на SO: It cannot have any explicit or implicit reference to this. So you cannot pass an inner class (even an anonymous one if it references any instance methods), or the result of a non-static method call, as a parameter. И правильно переводится как: Это [ вызов одного конструктора из другого с помощью this() или super() ] не может иметь никакой явной или неявной ссылки на "this". Поэтому вы не можете передать вложенный класс (...), или результат вызова нестатического метода в качестве параметра Почему? Потому что вы находитесь в конструкторе, а это значит, что ни объект, на который вы ссылаетесь через ключевое слово "this", ни объект внешнего класса еще не СОЗДАНЫ! Вот поэтому нельзя вызвать нестатический метод экземпляра этого класса. Вы просто не можете сделать что-либо с тем, что еще не существует! По той же причине также нельзя передать внутренний класс в качестве параметра конструктора, ведь согласно отличной статье про вложенные классы: Внутренний класс не может содержать статические переменные и методы., ведь без объекта «внешнего» класса доступа к внутреннему классу у нас не будет. А если рассматривать ситуацию с базовым классом и классом-потомком, то при вызове из потомка конструктора базового класса с помощью super(), нужно помнить, что сначала работает конструктор базового класса, а лишь потом инициализируются переменные класса-потомка. То есть вы, по сути, попытаетесь передать в конструктор класс, поля которого еще не инициализированы, конечно же это приведет к ошибке.
milyasow
Уровень 34
25 февраля 2022, 21:04
Дополню, конструкторы Java исключают рекурсию, как прямую, например вот так:
class A {
  public A(int x){
    this(1);
  }
}
так и косвенную, вот так:
class A {
  public A() {
    this(1);
  }
  public A(int x){
    this();
  }
}
Этот код компилятор просто не пропустит. Скорее именно это имел в виду автор оригинального ответа на Stack Overflow.
Crama
Уровень 7
20 февраля, 18:47
Вообще нихера не понятно...Вложенний, не вложенний, внутренний, внешний, херь сплошная. Хоть сам понял, что написал?
Dima_Sever
Уровень 18
21 апреля 2021, 13:53
Казалось бы мелочь, а очень важная мелочь. Большое Вам спасибо за статью!
Wiun
Уровень 16
17 марта 2021, 13:46
а так можно вызвать?
this.SomeClass(a, b);
this.c=c;
?
Wiun
Уровень 16
17 марта 2021, 13:57
сам отвечу, побаловавшись в идее. при создании класса мы или создаем конструктор и передаем значения его или же создаем метод и потом вызываем его на экземпляре класса. допустим у нас есть класс машина без явно заданного конструктора, но с методом getInfo.
public static class Car {
        int speed;
        int price;
        String model;

        public void getInfo(int speed, int price) {
            this.speed = speed;
            this.price = price;
        }
мы можем перегрузить метод, вызвав через this первый метод c уже указанными параметрами, чтобы опять заново их не задавать в методе. не знаю как правильно описать.
public void getInfo(int speed, int price, String model) {
           this.getInfo(speed, price);
           this.model = model;
       }
   }
при создании экземпляра машины у нас есть пустой конструктор
Car car = new Car();
и теперь, чтобы подставить параметры машины, нам надо вызвать метод Info
car.getInfo(90, 2500, "Opel");
понял лично для себя только так. можно было бы создать конструктор с 3 параметрами и сразу их передавать при создании экземпляра класса. то есть вот так
public Car(int speed, int price) {
            this.speed = speed;
            this.price = price;
        }
        public Car(int speed, int price, String model) {
            this(speed, price);
            this.model = model;
        }
Поправьте, если я не прав.
Andrei
Уровень 7
28 октября 2021, 15:46
this для вызова перегруженного метода getInfo() c двумя параметрами излишен. И так понятно что этот метод будет вызван из того же объекта.
public class Car {
    private int speed;
    private int price;
    private String model;

    public void setInfo(int speed, int price) {
        this.speed = speed;
        this.price = price;
    }

    public void setInfo(int speed, int price, String model) {
        setInfo(speed, price);
        this.model = model;
    }

    public void printInfo() {
        System.out.println("speed = " + speed + "\r\n" + "price = " + price + "\r\n" + "model = " + model);
    }

    public static void main(String[] args) {
        Car ford = new Car();
        ford.setInfo(220, 12000, "Ford");
        ford.printInfo();
    }
}
🦔 Виктор веду учебный тг-канал в t.me/Javangelion Expert
18 сентября 2020, 14:24
Спасибо, помогли решить задачу.
Alexandr
Уровень 23
12 сентября 2020, 14:12
Полезно
Andrew Petrushenkov
Уровень 9
15 мая 2020, 19:45
Отлично помогли, благодарю! Исправьте ошибку - "избежать (чего?) написаниЯ"
Григорий
Уровень 9
23 апреля 2020, 09:34
при вызове конструктора java автоматом определяет какой вызывать в зависимости от количества требуемых параметров?
Леонель Хантер
Уровень 16
25 апреля 2020, 08:10
угу
Glock
Уровень 13
13 апреля 2020, 05:37
Спасибо! мне помогло, может и простая вещь это, но затык был.
RedToad
Уровень 22
10 марта 2020, 18:50
По моему, бесполезная статья.
Igor Tarasov
Уровень 7
26 марта 2020, 05:19
по моему нет
Pavel Mordovin
Уровень 8
19 апреля 2022, 20:39
напишите полезную)))
Daniil Vishnivetsky
Уровень 9
10 февраля 2020, 12:58
Поделитесь видео по теме