Как мне вызвать один конструктор из другого в Java? - PullRequest
2055 голосов
/ 12 ноября 2008

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

Ответы [ 19 ]

2747 голосов
/ 12 ноября 2008

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

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

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

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

224 голосов
/ 12 ноября 2008

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

192 голосов
/ 12 марта 2013

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

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

  }

}
38 голосов
/ 24 апреля 2013

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

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);
   }
}
26 голосов
/ 26 мая 2015

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

}

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

15 голосов
/ 08 мая 2015

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

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

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

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

11 голосов
/ 07 января 2017

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

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

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

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

9 голосов
/ 16 ноября 2016

Да, в классе может присутствовать любое количество конструкторов, и они могут быть вызваны другим конструктором, используя 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 голосов
/ 21 ноября 2016

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

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

  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. this () вызов this должен быть первым оператором в конструкторе
  2. Это безымянный объект. это автоматически вызывает конструктор по умолчанию. 3.Это вызывает конструктор Parameterized.

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

7 голосов
/ 21 ноября 2017

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

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

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

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