1. 특징
    1. 객체가 생성될때 (new ClassName())인스턴스 초기화를 담당하는 특별한 메서드
    2. 객체 불변성 설정, final 필트 초기화 등에 사용된다.
    3. 이름 = 클래스명, 반환 타입 없음
    4. 오버로딩 가능(같은 이름, 다른 파라미터)
    5. 접근제어자 가능
      1. public, protected, private
    6. 기본 생성자
      1. 클래스에 생성자가 하나도 없으면 컴파일러가 매개변수 없는 기본 생성자를 자동 추가, 생성자를 하나라도 정의하면 자동 추가 안됨
    7. 체이닝: 같은 클래스 내에서 this(…), 부모 생성자는 super()
    8. 예외 던짐 가능
      1. 유효성 검사 실패 시 예외를 던질 수 있다.
    9. 실행시점 슈퍼클래스의 생성자 → 서브클래스 필드 초기화 및 생성자 순서
  2. 장점
    1. 객체가 항상 올바른 상태로 태어남
      1. 불변 필드 final을 초기화할 수 있음
      2. 캡슐화된 초기화
        1. 생성 시 필요한 유효성 검사를 강제할 수 있음
      3. 간결성
        1. new와 함께 바로 초기화 가능
      4. 오버로드로 다양한 생성 방식 제공
        1. 편의 생성자 vs 전체 초기화 생성자 구분 가능
    2. 단점
      1. 생성자에 무거운 작업을 두면 안됨
      2. 오버로딩이 많아지면 가독성/유지보수 악화
      3. 정적 팩토리보다 이름을 가질 수 없음
      4. 상속과 함께 사용 시 위험
      5. 프레임워크 제약
      6. 테스트 어려움
    3. 예시
      1. 기본/파라미터 생성자 & 유효성 검사

        public class Person{
        	private final String name;
        	private final int age;
        	
        	public Person(String name, int age){
        	
        		if(name ==null || name.isBlank()){
        			throw  new IllegalArgumentException("name은 필수 입니다.");
        		
        		}
        		
        		if(age < 0){
        			throw new IllegalArgumentException("age는 음수가 될 수 없습니다.");
        		}
        		   this.name = name;
                this.age = age;
        	}
        
        }
        

설명 : final 필드를 안전하게 초기화하고, 잘못된 상태 방지. 단점은 유효성 검사 실패 시 생성 자체가 예외로 끝남

  1. 오버로딩 + 체이닝 (this())

    public class Person{
    	private final String name;
    	private final int age;
    	private final String city;
    	
    	public Person(String name, int age, String city){
    		this.name = name;
    		this.age = age;
    		this.city = city;
    	}
    	public Person(Strign name, int age){
    		this(name, age,"unknown") //체이닝
    	}
    	  public Person(String name) {
            this(name, 0);
        }
    
    }
    
  2. 체이닝

    1. 말 그대로 연쇄 연결

    2. 생성자끼리 서로 연결해서 호출하는 패턴

    3. 목적: 중복 코드 제거 + 초기화 로직 통일

    4. 같은 클래스 내 체이닝 → this()

    5. 예시

      class A{
      	int x,y;
      	
      	A(int x, int y){
      		this.x=x;
      		this.y=y;
      	}
      	A(int x){
      		this(x,0); // 같은 클래스의 다른 생성자 호출
      	}	
      	A(){
      		this(0); //또 다른 생성자 호출
      	}
      }
      
    6. this() →같은 클래스의 다른 생성자 호출

    7. 중복 초기화 코드 방지

    8. 호출은 생성자 첫 줄 이어야함

    9. 부모 클래스 체이닝 → super()

      1. 예시
      class Parent{
      	int a;
      	Parent(int a) {this.a =a;}
      }
      
      class Child extends Parent{
      	int b;
      	Child(int a, int b){
      		super(a); //부모 생성자 호출
      		this.b = bl
      	
      	}
      
      }
      
      1. super → 부모 클래스 생성자 호출
      2. 자식 생성자는 항상 부모 생성자를 먼저 호출해야 객체가 올바르게 초기화됨
      3. 부모 생성자 호출도 반드시 첫 줄