constructor 자바 - Java에서 다른 생성자를 호출하는 방법은 무엇입니까?




생성자란 example (16)

다른 클래스로부터 생성자를 호출 할 수 있습니까 (서브 클래스가 아닌 동일한 클래스 내에서)? 그렇다면 어떻게? 다른 생성자를 호출하는 가장 좋은 방법은 무엇입니까 (여러 가지 방법이 있다면)?


Answers

이 키워드는 생성자에서 생성자를 호출하는 데 사용할 수 있습니다. 클래스에 대해 여러 생성자를 작성할 때 중복 코드를 피하기 위해 다른 생성자를 호출하려는 경우가 있습니다.

Bellow는 생성자와 getters () 및 setters ()에 대한 다른 주제를 설명하는 링크이며 두 생성자가있는 클래스를 사용했습니다. 설명과 예제가 도움이되기를 바랍니다.

Setter 메서드 또는 생성자


아주 간단하다.

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

희망이 도움이됩니다.


this(...) 키워드 (동일한 클래스에서 생성자를 호출해야하는 경우) 또는 super(...) 키워드 ( super(...) 클래스에서 생성자를 호출해야하는 경우 this(...) 를 통해 다른 생성자를 호출 할 수 있습니다.

그러나 이러한 호출은 생성자의 첫 번째 문이어야합니다. 이 제한을 극복 하려면 이 대답을 사용 하십시오 .


모두가 이미 말했듯 this(…) 명시 적 생성자 호출 이라고하는 this(…) 를 사용 this(…) .

그러나 그러한 명시 적 생성자 호출 문 내에서 참조 할 수는 없습니다.

  • 모든 인스턴스 변수 또는
  • 모든 인스턴스 메소드 또는
  • 이 클래스 나 슈퍼 클래스에서 선언 된 내부 클래스
  • this 또는
  • super .

JLS (§8.8.7.1)에 명시된 바와 같이


this(args) 사용 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에 대한 호출은 생성자의 첫 번째 호출이어야합니다. 그렇지 않으면 컴파일러 오류가 발생합니다.


예, 어떤 수의 생성자라도 클래스에 존재할 수 있으며 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");
    }
}

이를 생성자 오버로딩이라고합니다.
생성자의 경우 오버로딩 개념 만 적용 가능하고 상속이나 재정의는 적용되지 않습니다.


생성자 내에서 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;
    }

}

이 클래스에는 일련의 생성자가 포함되어 있습니다. 각 생성자는 사각형의 멤버 변수 일부 또는 전체를 초기화합니다.


Telescoping Constructor anti-pattern 또는 생성자 체인이라고합니다. 예, 당신은 확실히 할 수 있습니다. 위의 많은 예제를 보았습니다. 두 개 또는 세 개의 생성자 만 필요하다는 것을 알고 있으면 괜찮을 수도 있습니다. 그러나 더 필요한 경우 Builder 패턴과 같은 다른 디자인 패턴을 사용해보십시오. 예를 들면 다음과 같습니다.

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

더 필요할 수도 있습니다. 이 경우 빌더 패턴은 훌륭한 솔루션이 될 것입니다. 다음은 유용한 정보입니다. https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e design- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e the- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e pattern- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e the- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e constructor- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e pattern- https://medium.com/@modestofiguereo/design-patterns-2-the-builder-pattern-and-the-telescoping-constructor-anti-pattern-60a33de7522e


[ 참고 : 나는 다른 대답에서 볼 수 없었던 한 가지 측면을 추가하기를 원합니다 :이 줄이 첫 번째 줄에 있어야한다는 요구 사항의 한계를 극복하는 방법. ]

자바에서는 같은 클래스의 다른 생성자가 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;
  }
}

이것은 첫 번째 줄에 나타나야한다는 것이 큰 한계처럼 보이지만 정적 메서드를 통해 다른 생성자의 인수를 구성 할 수 있습니다. 예 :

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;

  }

}

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

첫 번째 줄이 아닌 코드 내부에서 다른 생성자를 호출해야 할 때 일반적으로 다음과 같은 도우미 메서드를 사용합니다.

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"키워드를 사용하여 같은 클래스의 다른 생성자에서 생성자를 생성 할 수 있습니다. 예 -

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 생성자로서의 문자열 .. 디폴트 생성자 .. arg 생성자로서의 int ..


예, 한 생성자를 다른 생성자로 호출 할 수 있습니다. 그러나 그것에 규칙이 있습니다. 한 생성자에서 다른 생성자로 호출이 이루어진 경우

새 생성자 호출은 현재 생성자의 첫 번째 문이어야합니다.

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

따라서이 경우에는 다른 생성자 호출도 먼저 다른 명령문보다 먼저 선언됩니다.


나는 너에게 쉬운 길을 말할 것이다.

생성자에는 가지 유형이 있습니다.

  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 () 호출은 생성자의 첫 번째 문이어야합니다.
  2. 이것은 이름이 적은 Object입니다. 이것은 자동으로 기본 생성자를 호출합니다. 3. 이것은 Parameterized 생성자를 호출합니다.

주 : 이것은 생성자의 첫 번째 명령문이어야합니다.


다른 생성자에서 생성자 호출

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

또한 super() 호출을 사용하여 상위 생성자를 호출 할 수 있습니다.


Visual C ++에서이 표기법을 생성자 내부에서 사용할 수도 있습니다 : this-> Classname :: Classname (다른 생성자의 매개 변수). 아래 예를 참조하십시오.

class Vertex
{
 private:
  int x, y;
 public:
  Vertex(int xCoo, int yCoo): x(xCoo), y(yCoo) {}
  Vertex()
  {
   this->Vertex::Vertex(-1, -1);
  }
};

다른 곳에서 작동하는지는 모르겠지만 Visual C ++ 2003 및 2008에서만 테스트했습니다.이 방법으로 여러 생성자를 호출 할 수도 있습니다. Java 및 C #과 비슷합니다.

추신 : 솔직히, 나는 이것이 이전에 언급되지 않았다는 것에 놀랐다.





java constructor