Dlise
시원한 냉장고
Dlise
전체 방문자
오늘
어제
  • 시원한 냉장고 (132)
    • Java (31)
      • Java (26)
      • Spring (5)
    • Algorithm & PS (25)
      • Algorithm (14)
      • Problem Solving (11)
    • Network (12)
    • Database (2)
    • Data Structure (4)
    • OOP & CleanCode (5)
    • Web (0)
    • Git (2)
    • AI (2)
    • Project (1)
      • Discord Bot (1)
    • Error (19)
    • Tools (5)
    • 수학 (5)
      • 확률과 통계(기초) (5)
    • 컴퓨터 구조 (3)
    • 활동 (16)
      • 행사 & 여행 (6)
      • 자격증 (4)
      • 회고 (6)
      • 기타 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 백준
  • java
  • 중위 표기법
  • 후위 표기법
  • 네트워크
  • 가장쉬운알고리즘책
  • spring security in action second edition
  • 통계학
  • CleanCode
  • 열혈강의자료구조

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Dlise
Java/Java

Java - 생성자, 초기화 블록

Java/Java

Java - 생성자, 초기화 블록

2023. 9. 25. 16:06

생성자와 초기화 블록에 대해 알아보자.

 

생성자

생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다.

인스턴스가 생성될 때 필요한 동작을 위해 활용한다.

 

생성자 구조

생성자는 클래스 이름과 같은 이름을 활용하며 반환값이 없다.

반환값이 없으므로 void만 올 수 있고 이를 생략한다.

 

아래 코드에서 Car() {...}가 생성자이다.

public class ConstructorPractice {
    public static void main(String[] args) {
        Car car = new Car();
    }
}

class Car {
    Car() {
        System.out.println("Hello world");
    }
}

 

이를 실행해 보면 Hello world가 출력된다.

인스턴스가 생성되고 생성자가 동작했기 때문이다.

 

기본 생성자

생성자를 구현하지 않아도 모든 클래스는 하나의 생성자를 가진다.

컴파일러가 기본 생성자를 추가하기 때문이다.

 

기본 생성자는 '클래스명() { }'의 형태로 되어있다.

만약 생성자를 하나라도 직접 구현했다면 기본 생성자는 추가되지 않는다.

 

 

생성자 오버로딩

생성자는 오버로딩이 가능해 여러 경우를 고려해 활용할 수 있다.

 

아래는 Car 클래스에 대해 2개의 생성자를 만든 코드이다.

Car 인스턴스를 생성할 때 인자로 정수를 보내면 Car(int door)를, 인자를 비우면 Car()를 실행한다.

public class ConstructorPractice {
    public static void main(String[] args) {
        Car car1 = new Car();
        Car car2 = new Car(2);

        System.out.println("car1: " + car1.door);
        System.out.println("car2: " + car2.door);
    }
}

class Car {
    int door;
    Car() {
        door = 4;
    }

    Car(int door) {
        this.door = door;
    }
}

 

 

생성자에서 다른 생성자 호출: this()

this()를 활용해 한 생성자에서 다른 생성자를 호출할 수 있다.

 

아래 코드는 Book 클래스에 대해 Book(), Book(String, int), Book(String, int, String) 3개의 생성자를 구현했다.

이후 Book()과 Book("Hello", 200) 인스턴스를 생성했다.

public class ConstructorPractice {
    public static void main(String[] args) {
        Book book = new Book();

        System.out.println(book.toString());
    }
}

class Book {
    String name;
    int pages;
    String color;

    Book() {
        this("Default", 100);
    }

    Book(String name, int pages) {
        this(name, pages, "Blue");
    }

    Book(String name, int pages, String color) {
        this.name = name;
        this.pages = pages;
        this.color = color;
    }

    public String toString() {
        return "name: " + name + ", pages: " + pages + ", color: " + color;
    }
}

결과는 아래와 같다.

 

먼저 Book()으로 Book 인스턴스를 생성한 경우 아래 코드가 실행되었다.

    Book() {
        this("Default", 100);
    }

 

Book() 생성자의 this(String, int)는 Book(String, int)를 호출했다.

    Book(String name, int pages) {
        this(name, pages, "Blue");
    }

 

Book(String, int) 생성자는 Book(String, int, String)을 호출했다.

    Book(String name, int pages, String color) {
        this.name = name;
        this.pages = pages;
        this.color = color;
    }

최종적으로 이 생성자에서 변수에 값을 담은 것이다.

 

단, this()는 생성자의 첫 줄에만 사용할 수 있다.

만약 아래와 같이 코드를 작성하면

    Book() {
        System.out.println("Test");
        this("Default", 100);
    }

컴파일 에러가 발생한다.

첫 줄에만 사용할 수 있는 이유는 만약 뒷 줄에 this()를 호출하면 기존의 초기화 작업이 무의미해지기 때문이다.

 

 

초기화 블록

초기화 블록은 마치 변수, 메서드처럼 클래스 초기화 블록과 인스턴스 초기화 블록이 있다.

실제로 차이점도 static의 유무이다.

public class InitBlockPractice {
    { }         //인스턴스 초기화 블록
    static { }  //클래스 초기화 블록
}

 

클래스 초기화 블록은 클래스가 메모리에 적재될 때 1회만 실행되며

인스턴스 초기화 블록은 인스턴스가 생성될 때마다 실행된다.

 

기억해야 할 것은 초기화 블록이 생성자보다 먼저 수행된다는 점이다.

public class InitBlockPractice {
    public static void main(String[] args) {
        Book book = new Book();
        System.out.println(book.name);
    }
}

class Book {
    String name;

    {
        name = "초기화 블록";
    }

    Book() {
        name = "생성자";
    }
}

위 코드의 출력 결과는 "생성자"이다.

 

생성자와 역할이 비슷한데 초기화 블록을 활용하는 이유는 생성자에서 반복되는 코드를 줄이기 위함이다.

 

아래는 사람이 1명씩 증가할 때마다 숫자를 1씩 늘려 입력하는 코드이다.

public class InitBlockPractice {
    public static void main(String[] args) {
        Person person1 = new Person();
        Person person2 = new Person("Happy");
        Person person3 = new Person("Cake");

        System.out.println(person1.toString());
        System.out.println(person2.toString());
        System.out.println(person3.toString());
    }
}

class Person {
    static int count;
    String name;
    int num;

    {
       count++;
       num = count;
    }

    Person() {
        name = "None";
    }

    Person(String name) {
        this.name = name;
    }

    public String toString() {
        return "번호: " + num + ", 이름: " + name;
    }
}

 

만약 초기화 블록을 사용하지 않으면 Person 클래스의 생성자는 중복되는 코드를 가져야 한다.

class Person {
    static int count;
    String name;
    int num;


    Person() {
        name = "None";
        count++;
        num = count;
    }

    Person(String name) {
        this.name = name;
        count++;
        num = count;
    }

    public String toString() {
        return "번호: " + num + ", 이름: " + name;
    }
}

만약 생성자가 더욱 많아지면 유지보수 측면에서 손해이다.

 

물론 아래 코드처럼 this()를 활용할 수는 있으나 

class Person {
    static int count;
    String name;
    int num;


    Person() {
        this("None");
    }

    Person(String name) {
        this.name = name;
        count++;
        num = count;
    }

    public String toString() {
        return "번호: " + num + ", 이름: " + name;
    }
}

동일한 작업을 한다는 점을 중요히 여겨 초기화 블록으로 구분해 놓는 것이 이후의 작업에 좋다.

 

 

클래스 초기화 블록

아래 코드는 클래스 초기화 블록을 사용한 것이다.

public class InitBlockPractice {
    public static void main(String[] args) {
        Person person1 = new Person("Happy");
        Person person2 = new Person("Cake");

        System.out.println(person1.toString());
        System.out.println(person2.toString());
    }
}

class Person {
    static int count;
    String name;
    int num;

    static {
        System.out.println("클래스 초기화 블록은 1회만 실행됩니다.");
    }

    Person(String name) {
        this.name = name;
        count++;
        num = count;
    }

    public String toString() {
        return "번호: " + num + ", 이름: " + name;
    }
}

출력이 처음 1회만 된 것을 알 수 있다.

'Java > Java' 카테고리의 다른 글

Java - Google Java Style Guide 정리  (3) 2023.10.10
Java - .of .asList .emptyList  (0) 2023.10.02
Java - Java 변수, 메서드  (0) 2023.09.24
Java - enum  (0) 2023.09.22
Java - Integer  (0) 2023.09.21
  • 생성자
  • 초기화 블록
'Java/Java' 카테고리의 다른 글
  • Java - Google Java Style Guide 정리
  • Java - .of .asList .emptyList
  • Java - Java 변수, 메서드
  • Java - enum
Dlise
Dlise

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.