Как вызвать один конструктор из другого в Java?

можно ли вызвать конструктор из другого (внутри того же класса, а не из подкласса)? Если да, то как? И что может быть лучшим способом вызвать другой конструктор (если есть несколько способов сделать это)?

18 ответов


Да, возможно:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

    public Foo(int x) {
        this.x = x;
    }
}

для привязки к определенному конструктору суперкласса вместо одного в том же классе используйте super вместо this. Обратите внимание, что вы можете подключаться только к одному конструктору и это должен быть первый оператор в вашем теле конструктора.

см. также этот вопрос, что касается C#, но где применяются те же принципы.


используя this(args). Предпочтительным шаблоном является работа от самого маленького конструктора до самого большого.

public class Cons {

 public Cons() {
  // A no arguments constructor that sends default values to the largest
  this(madeUpArg1Value,madeUpArg2Value,madeUpArg3Value);
 }

 public Cons(int arg1, int arg2) {
  // An example of a partial constructor that uses the passed in arguments
  // and sends a hidden default value to the largest
  this(arg1,arg2, madeUpArg3Value);
 }

 // Largest constructor that does the work
 public Cons(int arg1, int arg2, int arg3) {
  this.arg1 = arg1;
  this.arg2 = arg2;
  this.arg3 = arg3;
 }
}

вы также можете использовать более недавно пропагандируемый подход valueOf или просто "of":

public class Cons {
 public static Cons newCons(int arg1,...) {
  // This function is commonly called valueOf, like Integer.valueOf(..)
  // More recently called "of", like EnumSet.of(..)
  Cons c = new Cons(...);
  c.setArg1(....);
  return c;
 }
} 

чтобы вызвать супер класс, используйте super(someValue). Вызов super должен быть первым вызовом в конструкторе, или вы получите ошибку компилятора.


[Примечание: я просто хочу добавить один аспект, который я не видел в других ответах: как преодолеть ограничения требования, что это() должно быть на первой строке).]

в Java другой конструктор того же класса может быть вызван из конструктора через this(). Обратите внимание, однако, что this должно быть на первой строке.

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, 0.0);
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }
}

Это this должен появиться на первой линии выглядит как большое ограничение, но вы можете построить аргументы других конструкторов с помощью статических методов. Например:

public class MyClass {

  public MyClass(double argument1, double argument2) {
    this(argument1, argument2, getDefaultArg3(argument1, argument2));
  }

  public MyClass(double argument1, double argument2, double argument3) {
    this.argument1 = argument1;
    this.argument2 = argument2;
    this.argument3 = argument3;
  }

  private static double getDefaultArg3(double argument1, double argument2) {
    double argument3 = 0;

    // Calculate argument3 here if you like.

    return argument3;

  }

}

когда мне нужно вызвать другой конструктор из кода (не из первой строки), я обычно использую вспомогательный метод, например:

class MyClass {
   int field;


   MyClass() {
      init(0);
   } 
   MyClass(int value) {
      if (value<0) {
          init(0);
      } 
      else { 
          init(value);
      }
   }
   void init(int x) {
      field = x;
   }
}

но чаще всего я пытаюсь сделать это наоборот, вызывая более сложные конструкторы из более простых в первой строке, насколько это возможно. Для приведенного выше примера

class MyClass {
   int field;

   MyClass(int value) {
      if (value<0)
         field = 0;
      else
         field = value;
   }
   MyClass() {
      this(0);
   }
}

в конструкторе вы можете использовать this ключевое слово для вызова другого конструктора в том же классе. Это называется явный вызов конструктора.

вот еще один класс Rectangle с другой реализацией, отличной от реализации в разделе Objects.

public class Rectangle {
    private int x, y;
    private int width, height;

    public Rectangle() {
        this(1, 1);
    }
    public Rectangle(int width, int height) {
        this( 0,0,width, height);
    }
    public Rectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

}

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


как все уже сказали, вы используете this(…), которая называется явный вызов конструктора.

Однако имейте в виду, что внутри такого явного оператора вызова конструктора вы не можете ссылаться на

  • любой переменные или
  • любой методы экземпляра или
  • любой внутренние классы объявлено в этом классе или любом суперкласс, или
  • this или
  • super.

как указано в JLS (§8.8.7.1).


Я скажу вам простой способ

здесь два типы конструкторов:

  1. конструктор по умолчанию
  2. конструктора

я объясню в одном примере

class ConstructorDemo 
{
      ConstructorDemo()//Default Constructor
      {
         System.out.println("D.constructor ");
      }

      ConstructorDemo(int k)//Parameterized constructor
      {
         this();//-------------(1)
         System.out.println("P.Constructor ="+k);       
      }

      public static void main(String[] args) 
      {
         //this(); error because "must be first statement in constructor
         new ConstructorDemo();//-------(2)
         ConstructorDemo g=new ConstructorDemo(3);---(3)    
       }
   }                  

в приведенном выше примере я показал 3 типа вызова

  1. этот вызов () должен быть первым оператором в конструкторе
  2. это название меньше возражений. это автоматически вызывает конструктор по умолчанию. 3.Это вызывает параметризованный конструктор.

Примечание.: это должен быть первый оператор в конструкторе.


да, любое количество конструкторов может присутствовать в классе, и они могут быть вызваны другим конструктором с помощью this() [пожалуйста, не путайте this() вызов конструктора с this ключевое слово]. this() или this(args) должна быть первая строка в конструкторе.

пример:

Class Test {
    Test() {
        this(10); // calls the constructor with integer args, Test(int a)
    }
    Test(int a) {
        this(10.5); // call the constructor with double arg, Test(double a)
    }
    Test(double a) {
        System.out.println("I am a double arg constructor");
    }
}

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


Да можно вызвать один конструктор из другого. Но есть одно правило. Если вызов выполняется из одного конструктора в другой, то

этот новый вызов конструктора должен быть первым оператором в текущем конструкторе

public class Product {
     private int productId;
     private String productName;
     private double productPrice;
     private String category;

    public Product(int id, String name) {
        this(id,name,1.0);
    }

    public Product(int id, String name, double price) {
        this(id,name,price,"DEFAULT");
    }

    public Product(int id,String name,double price, String category){
        this.productId=id;
        this.productName=name;
        this.productPrice=price;
        this.category=category;
    }
}

Так, что-то вроде ниже не получится.

public Product(int id, String name, double price) {
    System.out.println("Calling constructor with price");
    this(id,name,price,"DEFAULT");
}

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

public class SuperClass {
    public SuperClass() {
       System.out.println("Inside super class constructor");
    }
}
public class SubClass extends SuperClass {
    public SubClass () {
       //Even if we do not add, Java adds the call to super class's constructor like 
       // super();
       System.out.println("Inside sub class constructor");
    }
}

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


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

class This1
{
    This1()
    {
        this("Hello");
        System.out.println("Default constructor..");
    }
    This1(int a)
    {
        this();
        System.out.println("int as arg constructor.."); 
    }
    This1(String s)
    {
        System.out.println("string as arg constructor..");  
    }

    public static void main(String args[])
    {
        new This1(100);
    }
}

выход - строка как конструктор arg.. Конструктор по умолчанию.. int как конструктор arg..


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

class MyConstructorDemo extends ConstructorDemo
{
    MyConstructorDemo()
    {
        this("calling another constructor");
    }
    MyConstructorDemo(String arg)
    {
        System.out.print("This is passed String by another constructor :"+arg);
    }
}

Также вы можете вызвать родительский конструктор с помощью super() вызов


да можно вызвать один конструктор из другого, с использованием this()

class Example{
   private int a = 1;
   Example(){
        this(5); //here another constructor called based on constructor argument
        System.out.println("number a is "+a);   
   }
   Example(int b){
        System.out.println("number b is "+b);
   }

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

Ниже приведена ссылка, по которой я объясняю другую тему о конструкторе и геттерах() и сеттерах (), и я использовал класс с двумя конструкторами. Надеюсь, объяснения и примеры помогут вам.

методы сеттера или конструкторы


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

С последней java и добавлением lambdas легко создать конструктор, который может принимать любой код инициализации, который вы хотите.

class LambdaInitedClass {

   public LamdaInitedClass(Consumer<LambdaInitedClass> init) {
       init.accept(this);
   }
}

называют его...

 new LambdaInitedClass(l -> { // init l any way you want });

очень просто

public class SomeClass{

    int number;
    String someString;

    public SomeClass(){
        number = 0;
    }

    public SomeClass(int number){
        this(); //set the class to 0
        this.setNumber(number); 
    }

    public SomeClass(int number, String someString){
        this(number); //call public SomeClass( int number )
    }

    public void setNumber(int number){
        this.number = number;
    }
    public void setString(String someString){
        this.someString = someString;
    }
    //.... add some accessors
}

теперь вот небольшой дополнительный кредит:

public SomeOtherClass extends SomeClass {
    public SomeOtherClass(int number, String someString){
         super(number, someString); //calls public SomeClass(int number, String someString)
    }
    //.... Some other code.
}

надеюсь, что это помогает.


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

    import java.util.*;
    import java.lang.*;

    class Test
    {  
        public static void main(String args[])
        {
            Dog d = new Dog(); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.
            Dog cs = new Dog("Bite"); // Both Calling Same Constructor of Parent Class i.e. 0 args Constructor.

            // You need to Explicitly tell the java compiler to use Argument constructor so you need to use "super" key word
            System.out.println("------------------------------");
            Cat c = new Cat();
            Cat caty = new Cat("10");

            System.out.println("------------------------------");
            // Self s = new Self();
            Self ss = new Self("self");
        }
    }

    class Animal
    {
        String i;

        public Animal()
        {
            i = "10";
            System.out.println("Animal Constructor :" +i);
        }
        public Animal(String h)
        {
            i = "20";
            System.out.println("Animal Constructor Habit :"+ i);
        }
    }

    class Dog extends Animal
    {
        public Dog()
        {
            System.out.println("Dog Constructor");
        }
        public Dog(String h)
        {
            System.out.println("Dog Constructor with habit");
        }
    }

    class Cat extends Animal
    {
        public Cat()
        {
            System.out.println("Cat Constructor");
        }
        public Cat(String i)
        {
            super(i); // Calling Super Class Paremetrize Constructor.
            System.out.println("Cat Constructor with habit");
        }
    }

    class Self
    {
        public Self()
        {
            System.out.println("Self Constructor");
        }
        public Self(String h)
        {
            this(); // Explicitly calling 0 args constructor. 
            System.out.println("Slef Constructor with value");
        }
    }

Вы можете вызвать другой конструктор через this(...) сайта (когда вам нужно вызвать конструктор из того же класса) или super(...) ключевое слово (когда вам нужно вызвать конструктор из суперкласса).

однако такой вызов должен быть первый заявление о конструкторе. К преодоление это ограничение, используйте ответ.


Он называется телескопическим конструктором anti-pattern или цепочкой конструктора. Да, определенно можешь. Я вижу много примеров выше, и я хочу добавить, что если вы знаете, что вам нужно только два или три конструктора, это может быть нормально. Но если вам нужно больше, пожалуйста, попробуйте использовать другой шаблон, как шаблон строителя. Например:

 public Omar(){};
 public Omar(a){};
 public Omar(a,b){};
 public Omar(a,b,c){};
 public Omar(a,b,c,d){};
 ...

вам может понадобиться больше. Шаблон Builder был бы отличным решением в этом случае. Вот статья, она может быть полезный https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e