it-swarm.com.de

Wie rufe ich einen Konstruktor von einem anderen in Java auf?

Ist es möglich, einen Konstruktor von einem anderen (innerhalb derselben Klasse, nicht von einer Unterklasse) aufzurufen? Wenn ja wie? Und wie kann man einen anderen Konstruktor am besten aufrufen (wenn es mehrere Möglichkeiten gibt)?

2093
ashokgelal

Ja, es ist möglich:

public class Foo {
    private int x;

    public Foo() {
        this(1);
    }

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

Verwenden Sie super anstelle von this, um eine Verkettung mit einem bestimmten Superklassenkonstruktor anstelle eines Konstruktors in derselben Klasse durchzuführen. Beachten Sie, dass Sie nur einen Konstruktor verketten können , und es muss die erste Anweisung in Ihrem Konstruktorkörper sein .

Siehe auch diese verwandte Frage , bei der es um C # geht, jedoch dieselben Prinzipien gelten.

2791
Jon Skeet

Mit this(args). Das bevorzugte Muster besteht darin, vom kleinsten Konstruktor bis zum größten zu arbeiten.

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

Sie können auch einen neueren Ansatz von valueOf oder "of" verwenden:

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

Verwenden Sie super(someValue), um eine Superklasse aufzurufen. Der Aufruf von super muss der erste Aufruf im Konstruktor sein, sonst wird ein Compilerfehler angezeigt.

232
Josh

[Anmerkung: Ich möchte nur einen Aspekt hinzufügen, den ich in den anderen Antworten nicht gesehen habe: wie man die Einschränkungen der Anforderung, dass this () in der ersten Zeile stehen muss, überwindet).]

In Java kann ein anderer Konstruktor derselben Klasse über this() aus einem Konstruktor aufgerufen werden. Beachten Sie jedoch, dass this in der ersten Zeile stehen muss.

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

Dass this in der ersten Zeile erscheinen muss, sieht nach einer großen Einschränkung aus, aber Sie können die Argumente anderer Konstruktoren über statische Methoden konstruieren. Zum Beispiel:

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

Wenn ich einen anderen Konstruktor aus dem Code heraus aufrufen muss (nicht in der ersten Zeile), verwende ich normalerweise eine Hilfsmethode wie die folgende:

class MyClass {
   int field;


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

Aber meistens versuche ich es umgekehrt, indem ich die komplexeren Konstruktoren so weit wie möglich von den einfacheren in der ersten Zeile abrufe. Für das obige Beispiel

class MyClass {
   int field;

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

Innerhalb eines Konstruktors können Sie das Schlüsselwort this verwenden, um einen anderen Konstruktor in derselben Klasse aufzurufen. Dies wird als expliziter Konstruktoraufruf bezeichnet.

Hier ist eine weitere Rectangle-Klasse mit einer anderen Implementierung als im Abschnitt "Objekte".

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

}

Diese Klasse enthält eine Reihe von Konstruktoren. Jeder Konstruktor initialisiert einige oder alle Mitgliedsvariablen des Rechtecks.

26
amila isura

Wie alle bereits gesagt haben, verwenden Sie this(…), das als expliziter Konstruktoraufruf bezeichnet wird.

Beachten Sie jedoch, dass innerhalb einer solchen expliziten Konstruktoraufrufanweisung auf die Sie möglicherweise nicht verweisen

  • beliebige Instanzvariablen oder
  • beliebige Instanzmethoden oder
  • beliebige innere Klassen , die in dieser Klasse oder einer beliebigen Oberklasse deklariert sind, oder
  • this oder
  • super.

Wie in JLS angegeben (§8.8.7.1).

15
olovb

Ja, es ist möglich, einen Konstruktor von einem anderen aufzurufen. Aber es gibt eine Regel. Wenn ein Aufruf von einem Konstruktor zu einem anderen erfolgt, dann

dieser neue Konstruktoraufruf muss die erste Anweisung im aktuellen Konstruktor sein

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

So etwas wie unten wird nicht funktionieren.

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

Im Falle einer Vererbung wird beim Erstellen des Objekts einer Unterklasse zuerst der Superklassenkonstruktor aufgerufen.

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

In diesem Fall wird also auch ein anderer Konstruktoraufruf zuerst vor allen anderen Anweisungen deklariert.

11
S R Chaitanya

Ja, eine beliebige Anzahl von Konstruktoren kann in einer Klasse vorhanden sein und von einem anderen Konstruktor mit this() [Bitte verwechseln Sie den Konstruktoraufruf this() nicht mit dem Schlüsselwort this] aufgerufen werden. this() oder this(args) sollte die erste Zeile im Konstruktor sein.

Beispiel:

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

Dies wird als Konstruktorüberladung bezeichnet.
Bitte beachten Sie, dass für Konstruktoren nur das Überladungskonzept gilt und keine Vererbung oder Überschreibung.

9
Utsav

Ich erzähle Ihnen einen einfachen Weg

Es gibt zwei Arten von Konstruktoren:

  1. Standardkonstruktor
  2. Parametrisierter Konstruktor

Ich werde in einem Beispiel erklären

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

Im obigen Beispiel habe ich 3 Arten von Anrufen gezeigt

  1. der Aufruf von this () muss die erste Anweisung im Konstruktor sein
  2. Dies ist Name minus Objekt. Dies ruft automatisch den Standardkonstruktor auf. 3.Dies ruft den parametrisierten Konstruktor auf.

Anmerkung: Dies muss die erste Anweisung im Konstruktor sein.

Sie können einen Konstruktor von einem anderen Konstruktor derselben Klasse mithilfe des Schlüsselworts "this" erstellen. Beispiel -

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

Ausgabe - String als Argumentkonstruktor .. Standardkonstruktor .. int als Argumentkonstruktor ..

7
ABHISHEK RANA

Ziemlich einfach

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
}

jetzt hier ein kleiner extra kredit:

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

Hoffe das hilft.

7
GetBackerZ

Konstruktor von einem anderen Konstruktor aufrufen

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

Sie können den übergeordneten Konstruktor auch mit super() aufrufen

7
Akshay Gaikwad

Ja, es ist möglich, einen Konstruktor von einem anderen mit this() aufzurufen.

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

Mit dem Schlüsselwort this kann ein Konstruktor aus einem Konstruktor aufgerufen werden, wenn mehrere Konstruktoren für a geschrieben werden Klasse, es gibt Zeiten, in denen Sie einen Konstruktor von einem anderen aufrufen möchten, um doppelten Code zu vermeiden.

Bellow ist ein Link, über den ich andere Themen zu Konstruktoren und getters () und setters () erläutere. Außerdem habe ich eine Klasse mit zwei Konstruktoren verwendet. Ich hoffe die Erklärungen und Beispiele helfen Ihnen weiter.

Setter-Methoden oder Konstruktoren

5
S. Mayol

Es gibt Entwurfsmuster, die die Notwendigkeit komplexer Konstruktionen abdecken. Wenn dies nicht präzise möglich ist, erstellen Sie eine Factory-Methode oder eine Factory-Klasse.

Mit dem neuesten Java und der Hinzufügung von Lambdas ist es einfach, einen Konstruktor zu erstellen, der jeden gewünschten Initialisierungscode akzeptieren kann.

class LambdaInitedClass {

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

Nennen Sie es mit ...

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

Es heißt Telescoping Constructor Anti-Pattern oder Konstruktor-Verkettung. Ja, das kannst du definitiv. Ich sehe oben viele Beispiele und möchte hinzufügen, dass es in Ordnung sein könnte, wenn Sie wissen, dass Sie nur zwei oder drei Konstruktoren benötigen. Wenn Sie jedoch mehr benötigen, versuchen Sie bitte, ein anderes Entwurfsmuster wie das Builder-Muster zu verwenden. Wie zum Beispiel:

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

Möglicherweise benötigen Sie mehr. Builder-Muster wären in diesem Fall eine gute Lösung. Hier ist ein Artikel, der hilfreich sein könnte https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e

4

Ich weiß, dass es so viele Beispiele für diese Frage gibt, aber was ich gefunden habe, gebe ich hier an, um meine Idee zu teilen. Es gibt zwei Möglichkeiten, Konstruktoren zu verketten. In der gleichen Klasse können Sie dieses Schlüsselwort verwenden. Bei der Vererbung müssen Sie das Schlüsselwort super verwenden.

    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

Sie können einen anderen Konstruktor über das Schlüsselwort this(...) (wenn Sie einen Konstruktor aus derselben Klasse aufrufen müssen) oder das Schlüsselwort super(...) (wenn Sie einen Konstruktor aus einem aufrufen müssen) aufrufen Superklasse).

Ein solcher Aufruf muss jedoch die erste Anweisung Ihres Konstruktors sein. Um diese Einschränkung zu überwinden , verwenden Sie diese Antwort .

4
John McClane

Ursprünglich aus einem Anser von Mirko Klemm, leicht modifiziert, um die Frage zu beantworten:

Der Vollständigkeit halber: Es gibt auch den Instanzinitialisierungsblock , der immer ausgeführt wird, bevor ein anderer Konstruktor aufgerufen wird. Es besteht einfach aus einem Anweisungsblock "{...}" irgendwo im Hauptteil Ihrer Klassendefinition. Sie können sogar mehrere haben. Sie können sie nicht aufrufen, aber sie sind wie Code für gemeinsam genutzte Konstruktoren, wenn Sie Code über Konstruktoren hinweg wiederverwenden möchten, ähnlich wie beim Aufrufen von Methoden.

Also in deinem Fall

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

Es gibt auch eine "statische" Version, um statische Member zu initialisieren: "static {...}"

1
rogerdpack

Ich bevorzuge diesen Weg:

    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

Ja, Sie können Konstruktoren von anderen Konstruktoren aufrufen. Zum Beispiel:

public class Animal {
    private int animalType;

    public Animal() {
        this(1);
    }

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

sie können auch Details aus Constructor Chaining in Java einlesen

0
Soni Vashisht