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

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

+2060
12 нояб. '08 в 20:10
источник поделиться
20 ответов

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

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

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

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

+2753
12 нояб. '08 в 20:12
источник

Используя 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 должен быть первым вызовом в конструкторе, иначе вы получите ошибку компилятора.

+225
12 нояб. '08 в 20:13
источник

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

В 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;

  }

}
+192
11 мар. '13 в 20:33
источник

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

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);
   }
}
+38
23 апр. '13 в 23:12
источник

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

Вот еще один класс Rectangle с другой реализацией от той, что находится в разделе "Объекты".

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;
    }

}

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

+26
26 мая '15 в 15:09
источник

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

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

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

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

+15
07 мая '15 в 22:52
источник

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

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

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 constructor like 
       // super();
       System.out.println("Inside sub class constructor");
    }
}

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

+11
07 янв. '17 в 13:21
источник

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

Существует два типа конструкторов:

  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. Он вызывает конструктор Parameterized.

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

+9
21 нояб. '16 в 13:14
источник

Да, любое число конструкторов может присутствовать в классе, и их можно вызвать другим конструктором, используя this() [Пожалуйста, не путайте 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");
    }
}

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

+9
16 нояб. '16 в 16:14
источник

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

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

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

+7
03 мар. '17 в 9:27
источник

Довольно просто

public class SomeClass{

    private int number;
    private String someString;

    public SomeClass(){
        number = 0;
        someString = new String();
    }

    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 )
        this.setString(someString);
    }

    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.
}

Надеюсь это поможет.

+7
21 нояб. '17 в 14:03
источник

Вы можете создать конструктор из другого конструктора того же класса с помощью ключевого слова "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);
    }
}

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

+7
27 нояб. '15 в 19:01
источник

Да, можно вызвать один конструктор из другого с помощью 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);
   }
+6
13 сент. '16 в 5:48
источник

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

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

Методы или конструкторы сеттеров

+5
14 мар. '17 в 23:53
источник

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

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

class LambdaInitedClass {

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

Позвонить с помощью...

 new LambdaInitedClass(l -> { // init l any way you want });
+5
13 нояб. '17 в 23:01
источник

Я знаю, что есть так много примеров этого вопроса, но то, что я нашел, я помещаю здесь, чтобы поделиться своей идеей. существует два способа построения конструктора. В том же классе вы можете использовать это ключевое слово. в Inheritance вам нужно использовать ключевое слово 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");
        }
    }
+4
24 янв. '18 в 5:45
источник

Это называется привязкой к троекрату или цепочке конструкторов Telescoping Constructor. Да, вы можете это сделать. Я вижу много примеров выше, и я хочу добавить, сказав, что если вы знаете, что вам нужен только два или три конструктора, возможно, все в порядке. Но если вам нужно больше, попробуйте использовать другой шаблон дизайна, такой как шаблон Builder. Как например:

 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

+4
06 июн. '18 в 19:36
источник

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

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

+4
29 июл. '18 в 1:14
источник

Первоначально от anser Мирко Клемм, немного изменен для решения вопроса:

Просто для полноты: есть также блок инициализации Instance, который выполняется всегда и до вызова любого другого конструктора. Он состоит просто из блока операторов "{...}" где-то в теле определения вашего класса. Вы можете даже иметь более одного. Вы не можете вызывать их, но они похожи на код "общего конструктора", если вы хотите повторно использовать некоторый код в конструкторах, подобно вызову методов.

Так что в вашем случае

{ 
  System.out.println("this is shared constructor code executed before the constructor");
  field1 = 3;
}

Существует также "статическая" версия этого для инициализации статических членов: "статический {...}"

+1
09 апр. '19 в 0:30
источник

Я предпочитаю этот способ:

    class User {
        private long id;
        private String username;
        private int imageRes;

    public User() {
        init(defaultID,defaultUsername,defaultRes);
    }
    public User(String username) {
        init(defaultID,username, defaultRes());
    }

    public User(String username, int imageRes) {
        init(defaultID,username, imageRes);
    }

    public User(long id, String username, int imageRes) {
        init(id,username, imageRes);

    }

    private void init(long id, String username, int imageRes) {
        this.id=id;
        this.username = username;
        this.imageRes = imageRes;
    }
}
0
19 июн. '19 в 8:38
источник

Посмотрите другие вопросы по меткам или Задайте вопрос