web-dev-qa-db-fra.com

Comment appeler un constructeur d'un autre en Java?

Est-il possible d'appeler un constructeur depuis un autre (dans la même classe, pas depuis une sous-classe)? Si oui comment? Et quel pourrait être le meilleur moyen d'appeler un autre constructeur (s'il existe plusieurs façons de le faire)?

2093
ashokgelal

Oui c'est possible:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

Pour chaîner à un constructeur de superclasse particulier au lieu d'un constructeur de la même classe, utilisez super à la place de this. Notez que vous ne pouvez chaîner qu’à un seul constructeur , et doit être la première instruction de votre corps de constructeur .

Voir aussi cette question connexe , qui concerne C # mais où les mêmes principes s'appliquent.

2791
Jon Skeet

Utiliser this(args). Le modèle préféré consiste à travailler du plus petit constructeur au plus grand.

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

Vous pouvez également utiliser une approche plus récemment préconisée de valueOf ou simplement "de":

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

Pour appeler une super classe, utilisez super(someValue). L'appel à super doit être le premier appel du constructeur, sinon vous obtiendrez une erreur du compilateur.

232
Josh

[Remarque: je veux juste ajouter un aspect, que je n'ai pas vu dans les autres réponses: comment surmonter les limitations de l'exigence selon laquelle this () doit être sur la première ligne).]

Dans Java, un autre constructeur de la même classe peut être appelé depuis un constructeur via this(). Notez cependant que this doit être sur la première ligne.

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

Le fait que this doive apparaître sur la première ligne semble être une grosse limitation, mais vous pouvez construire les arguments d'autres constructeurs via des méthodes statiques. Par exemple:

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;

  }

}
194
Christian Fries

Lorsque j'ai besoin d'appeler un autre constructeur à l'intérieur du code (pas sur la première ligne), j'utilise généralement une méthode d'assistance comme celle-ci:

class MyClass {
   int field;


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

Mais le plus souvent, j'essaie de faire l'inverse en appelant les constructeurs les plus complexes, des plus simples à la première ligne, dans la mesure du possible. Pour l'exemple ci-dessus

class MyClass {
   int field;

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

Dans un constructeur, vous pouvez utiliser le mot clé this pour appeler un autre constructeur de la même classe. Cela s'appelle un appel de constructeur explicite.

Voici une autre classe Rectangle, avec une implémentation différente de celle de la section Objets.

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

}

Cette classe contient un ensemble de constructeurs. Chaque constructeur initialise tout ou partie des variables membres du rectangle.

26
amila isura

Comme tout le monde l’a déjà dit, vous utilisez this(…), appelé invocation de constructeur explicite .

Cependant, gardez à l'esprit que dans une telle instruction d'invocation de constructeur explicite vous ne pouvez pas vous en référer

  • toute variable d'instance ou
  • toute méthode d'instance ou
  • toute classe interne déclarée dans cette classe ou toute superclasse, ou
  • this ou
  • super.

Comme indiqué dans JLS (§8.8.7.1).

15
olovb

Oui, il est possible d'appeler un constructeur d'un autre. Mais il y a une règle à cela. Si un appel est passé d’un constructeur à un autre, alors

ce nouvel appel de constructeur doit être la première instruction du constructeur actuel

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

Donc, quelque chose comme ci-dessous ne fonctionnera pas.

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

De même, en cas d'héritage, lorsque l'objet de la sous-classe est créé, le constructeur de la super-classe est d'abord appelé.

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

Ainsi, dans ce cas, un autre appel de constructeur est d'abord déclaré avant toute autre instruction.

11
S R Chaitanya

Oui, un nombre quelconque de constructeurs peuvent être présents dans une classe et ils peuvent être appelés par un autre constructeur à l'aide de this() [Veuillez ne pas confondre this() appel du constructeur avec this mot clé]. this() ou this(args) devrait être la première ligne du constructeur.

Exemple:

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

Ceci est connu sous le nom de surcharge du constructeur.
Veuillez noter que pour le constructeur, seul le concept de surcharge est applicable et non l'héritage ou le dépassement.

9
Utsav

Je vais vous dire un moyen facile

Il existe deux types de constructeurs:

  1. constructeur par défaut
  2. constructeur paramétré

Je vais expliquer dans un exemple

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

Dans l'exemple ci-dessus, j'ai montré 3 types d'appels

  1. cet appel () à this doit être la première déclaration du constructeur
  2. Ceci est Nom moins objet. cela appelle automatiquement le constructeur par défaut. 3.Cela appelle le constructeur paramétré.

Remarque: il doit s'agir de la première instruction du constructeur.

Vous pouvez utiliser un constructeur d'un autre constructeur de la même classe en utilisant le mot clé "this". Exemple -

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

Sortie - chaîne en tant que constructeur arg .. Constructeur par défaut .. int en tant que constructeur arg ..

7
ABHISHEK RANA

Assez simple

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
}

maintenant voici un petit crédit supplémentaire:

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

J'espère que cela t'aides.

7
GetBackerZ

Appel du constructeur depuis un autre constructeur

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

Vous pouvez aussi appeler le constructeur parent en utilisant super() call

7
Akshay Gaikwad

Oui, il est possible d'appeler un constructeur d'un autre en utilisant 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
Akash Manngroliya

Le mot clé this peut être utilisé pour appeler un constructeur à partir d'un constructeur, lors de l'écriture de plusieurs constructeurs pour un classe, il peut arriver que vous souhaitiez appeler un constructeur d’un autre pour éviter le code en double.

Ci-dessous un lien qui explique d'autres sujets sur constructeur et getters () et setters () et j'ai utilisé une classe avec deux constructeurs. J'espère que les explications et les exemples vous aideront.

méthodes Setter ou constructeurs

5
S. Mayol

Il existe des modèles de conception qui couvrent le besoin de construction complexe - si cela ne peut pas être fait de manière succincte, créez une méthode ou une classe d'usine.

Avec le dernier Java et l'ajout de lambdas, il est facile de créer un constructeur pouvant accepter le code d'initialisation souhaité.

class LambdaInitedClass {

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

Appelez ça avec ...

 new LambdaInitedClass(l -> { // init l any way you want });
5
Rodney P. Barbati

C'est ce qu'on appelle l'anti-dessin ou l'enchaînement des constructeurs du constructeur télescopique. Oui, vous pouvez certainement faire. Je vois beaucoup d'exemples ci-dessus et je veux ajouter en disant que si vous savez que vous n'avez besoin que de deux ou trois constructeurs, cela pourrait aller. Mais si vous avez besoin de plus, essayez d’utiliser un modèle différent, tel que le modèle Builder. Comme par exemple:

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

Vous aurez peut-être besoin de plus. Le motif constructeur serait une excellente solution dans ce cas. Voici un article, il pourrait être utile https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti -pattern-60a33de7522e

4

Je sais qu'il y a tellement d'exemples de cette question mais ce que j'ai trouvé, je le mets ici pour partager mon idée. il y a deux façons de chaîner le constructeur. Dans la même classe, vous pouvez utiliser ce mot clé. En héritage, vous devez utiliser le mot-clé 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
Negi Rox

Vous pouvez appeler un autre constructeur à l'aide du mot clé this(...) (lorsque vous devez appeler un constructeur de la même classe) ou du mot clé super(...) (lorsque vous devez appeler un constructeur à partir d'un superclasse).

Cependant, un tel appel doit être la première déclaration de votre constructeur. Pour surmonter cette limitation, utilisez cette réponse .

4
John McClane

À l'origine d'un anser de Mirko Klemm, légèrement modifié pour répondre à la question:

Juste pour être complet: Il y a aussi le bloc d'initialisation de l'instance qui est exécuté toujours et avant l'appel de tout autre constructeur. Cela consiste simplement en un bloc d'instructions "{...}" quelque part dans le corps de votre définition de classe. Vous pouvez même en avoir plus d'un. Vous ne pouvez pas les appeler, mais ils s'apparentent à du "code de constructeur partagé" si vous souhaitez réutiliser du code sur des constructeurs, comme les méthodes d'appel.

Donc dans ton cas

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

Il existe également une version "statique" de cette commande pour initialiser les membres statiques: "static {...}"

1
rogerdpack

Je préfère cette façon:

    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;
    }
}
1
ansh sachdeva

Oui, vous pouvez appeler des constructeurs depuis un autre constructeur. Par exemple:

public class Animal {
    private int animalType;

    public Animal() {
        this(1);
    }

    public Animal(String animalType) {
        this.animalType = animalType;
    }
}

vous pouvez également lire les détails de Chaînage de constructeurs en Java

0
Soni Vashisht