[코드스테이츠 백엔드 44기 SEB BE] 10일차

오태호·2023년 2월 24일
0

코드스테이츠

목록 보기
10/22
post-thumbnail

생성자(Constructor)

  • 객체를 생성하는 역할을 하는 클래스의 구성요소
  • 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드
  • new 키워드를 사용하여 객체를 생성할 때 호출됨
    • 여기서 인스턴스 생성을 담당하는 것은 new 키워드
    • 생성자는 인스턴스 변수들을 초기화하는 데에 사용되는 특수한 메서드
  • 생성자의 특징을 잘 이해한다면 보다 간결하고 직관적인 코드 작성이 가능함
  • 생성자의 조건
    1. 생성자의 이름은 반드시 클래스의 이름과 같아야 함
      • 클래스 이름과 생성자의 이름이 다르다면 생성자의 기능을 수행할 수 없음
    2. 생성자는 리턴 타입이 없음
      • void 키워드
        • 무언가를 리턴하지 않는다는 의미
      • 생성자는 리턴 타입 자체가 없으므로 void 키워드 또한 사용하지 않음
클래스명(매개변수) {
    // 생성자의 기본 구조
}
  • 매개변수는 존재할 수도, 존재하지 않을 수도 있음
  • 생성자 또한 오버로딩이 가능함
    • 한 클래스 내에 여러 개의 생성자가 존재할 수 있다!
public class Person {
    String name, address;
    int age;

    public Person() {} // 1번 생성자

    public Person(String name, int age) { // 2번 생성자
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) { // 3번 생성자
        this.name = name;
        this.age = age;
        this.address = address;
    }
}
  • 생성자의 모양에 따라 객체를 생성하는 방법이 결정됨
    • 2번 생성자를 호출할 때에는 객체 생성 시에 문자열 및 정수형 숫자 하나씩 전달해줘야 함
    • 3번 생성자를 호출할 때에는 두 개의 문자열 및 정수형 숫자 하나를 전달해줘야 함
    • 기본 생성자
      • 1번 생성자 즉, 매개변수가 없는 생성자

기본 생성자 vs 매개변수가 있는 생성자

기본 생성자(Default Constructor)

  • 모든 클래스에는 하나 이상의 생성자가 존재하는데, 클래스에 따로 생성자를 만들지 않아도 인스턴스를 생성할 수 있었음
    • 자바 컴파일러는 생성자가 클래스 안에 포함되어있지 않는다면 기본 생성자를 자동으로 추가해줌
    • 만약 생성자가 이미 클래스에 존재한다면 해당 생성자를 기본으로 사용함
  • 기본 생성자
    • 매개변수가 없는 생성자
클래스명() {}

// 예시
Person() {}
  • 컴파일러가 자동으로 추가해주는 기본 생성자는 위 예시처럼 바디에는 아무 내용이 들어가있지 않음

매개변수가 있는 생성자

  • 매개변수를 통해 호출하여 해당 값으로 인스턴스를 초기화하는 데에 사용
  • 고유한 특성을 가지는 인스턴스를 여러 개 만들어야하는 경우, 인스턴스마다 각기 다른 값을 가지고 초기화할 수 있음
class Person {
    private String name;
    private String address;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) {
        this.name = name;
        this.age = age;
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

public class Main {
    public static void main(String[] args) {
        Person p = new Person("홍길동", 20);
        System.out.println("제 이름은 " + p.getName() + "이고, 나이는 " + p.getAge() + "입니다.");
    }
}
  • Person 인스턴스 생성 시에 매개변수가 있는 생성자를 사용하면
    • 인스턴스를 만든 후에 인스턴스의 필드값을 생성과 동시에 원하는 값으로 설정

this()

  • 메서드 안에 생성자는 상호 호출이 가능
    • 이를 위해 사용하는 것이 this() 메서드
  • this() 메서드
    • 자신이 속한 클래스의 다른 생성자를 호출하는 데에 사용
  • this() 메서드 사용을 위한 요소
    1. this() 메서드는 생성자의 내부에서만 사용할 수 있다!
    2. this() 메서드는 반드시 생성자의 첫 줄에 위치해야 한다!

생성자에서 다른 생성자를 첫 줄에서만 호출이 가능하도록 한 이유는?

  • 생성자 내에서 초기화 작업 도중 다른 생성자를 호출하게 되면, 호출된 다른 생성자 내에서도 멤버변수들의 값을 초기화 할 것이다. 이로 인해 다른 생성자를 호출하기 이전의 초기화 작업이 무의미해질 수 있다.
class Person {
    private String name;
    private String address;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) {
        this(name, age);
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

public class Test {
    public static void main(String[] args) {
        Person person1 = new Person("홍길동", 20, "서울시");
    }
}
  • Person 클래스는 2개의 생성자를 가짐
    1. 매개변수가 문자열 하나, 정수형 하나인 생성자
    2. 매개변수가 문자열 2개, 정수형 하나인 생성자
      • 이 생성자 내부의 첫 번째 줄에 this() 메서드가 포함되어 있음
  • Person 클래스를 기반으로 만들어지는 인스턴스를 두 번째 생성자를 사용하여 생성하면,
    • 생성자가 호출되면 this() 메서드가 호출되고 그에 따라 첫 번째 생성자가 호출되어 name, age 값이 초기화되고 그 다음으로 address의 값이 초기화됨

this 키워드

class Person {
    private String name;
    private String address;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person(String name, int age, String address) {
        this(name, age);
        this.address = address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}
  • Person 클래스를 보면, 인스턴스 변수로 name, age, address가 선언되어 있고 두 번째 생성자의 매개변수로 name, age, address가 정의되어 있음
    • 인스턴스 변수와 생성자의 매개변수 이름이 같아 구분하기가 어려움
    • 이 때, this 키워드를 사용
  • this 키워드
    • 모든 메서드에는 자신이 포함된 클래스의 객체를 가리키는 this라는 참조변수가 있음
    • 일반적으로 컴파일러가 this. 을 추가해주기 때문에 생략하는 경우가 많음
  • this는 인스턴스 자신을 가리키며, this를 통해 인스턴스 자신의 변수에 접근할 수 있음
  • this 키워드는 주로 인스턴스의 필드명과 지역변수를 구분하기 위한 용도로 사용됨

내부 클래스

내부 클래스

  • 클래스 내에 선언된 클래스
  • 외부 클래스와 내부 클래스가 연관되어 있을 때 사용
  • 내부 클래스를 사용하면
    1. 외부 클래스의 멤버들에 쉽게 접근할 수 있음
    2. 코드의 복잡성을 줄일 수 있음
    3. 외부적으로 불필요한 데이터를 감출 수 있어 캡슐화(encapsulation)를 달성하는 데에 유용함
class OuterClass {
    class InnerClass {
        // 인스턴스 내부 클래스
    }

    static class StaticInnreClass {
        // 정적 내부 클래스
    }

    void main() {
        class LocalInnerClass {
            // 지역 내부 클래스
        }
    }
}
  • 내부 클래스의 종류
    1. 인스턴스 내부 클래스
    2. 정적 내부 클래스
    3. 지역 내부 클래스
    4. 익명 내부 클래스
      • 클래스의 선언과 객체의 생성을 동시에 수행하는 일회용 내부 클래스
  • 익명 내부 클래스를 제외한 세 가지 내부 클래스는 선언 위치를 중심으로 구분될 수 있고, 유효범위(scope)와 특성이 변수의 것과 유사함
종류선언 위치사용 가능한 변수
인스턴스 내부 클래스(Instance inner class)외부 클래스의 멤버변수 선언 위치에 선언(멤버 내부 클래스)외부 인스턴스 변수, 외부 전역 변수
정적 내부 클래스(Static inner class)외부 클래스의 멤버변수 선언 위치에 선언(멤버 내부 클래스)외부 전역 변수
지역 내부 클래스(Local inner class)외부 클래스의 메서드나 초기화 블럭 안에 선언외부 인스턴스 변수, 외부 전역 변수
익명 내부 클래스(Anonymous inner class)클래스의 선언과 객체의 생성을 동시에 하는 일회용 익명 클래스외부 인스턴스 변수, 외부 전역 변수

멤버 내부 클래스

  • 인스턴스 내부 클래스, 정적 내부 클래스를 하나로 묶어 통칭하는 용어

인스턴스 내부 클래스

  • 객체 내부에 멤버 형태로 존재
  • 외부 클래스의 모든 접근 지정자의 멤버에 접근 가능
class Car { // 외부 클래스
    private String model; // 외부 클래스 인스턴스 변수
    private static int maxFuel; // 외부 클래스 정적 변수

    private Blackbox blackbox; // 내부 클래스 자료형 변수 선언

    public Car() {
        blackbox = new Blackbox();
    }

    class Blackbox { // 인스턴스 내부 클래스
        String model;
        int recordTime = 0; // 내부 클래스의 인스턴스 변수

        void Blackbox() {
            model = null;
            recordTime = 0;
        }

        void print() {
            System.out.println(model);
            System.out.println(maxFuel);
            System.out.println(recordTime);
        }
    }
}
  • 인스턴스 내부 클래스는 private 접근 제어자를 사용하고 있음에도 내부에서 외부 클래스의 인스턴스 변수와 정적 변수에 각각 접근하여 해당 값을 사용
  • 인스턴스 내부 클래스는 외부 클래스를 생성한 이후에 사용해야 한다!
    • 클래스 생성과 상관없이 사용할 수 있는 정적 변수와 정적 메서드는 인스턴스 내부 클래스에서 선언할 수 없다!

정적 내부 클래스

  • 인스턴스 내부 클래스와 동일하게 클래스의 멤버 변수 위치에 정의
    • 그러나 static 키워드를 사용
  • 내부 클래스가 외부 클래스의 존재와 무관하게 정적 변수를 사용할 수 있게 할 때 정적 내부 클래스를 사용
class Car { // 외부 클래스
    private String model; // 외부 클래스 인스턴스 변수
    private static int maxFuel; // 외부 클래스 정적 변수

    static void printTest() {
        System.out.println("Car 클래스");
    }

    void printTest2() {
        System.out.println("인스턴스 메서드");
    }

    static class Blackbox { // 정적 내부 클래스
       void print() {
            System.out.println(maxFuel);
            printTest();
        }
    }
}
  • 위 예시를 보면 정적 내부 클래스 내에서 외부 클래스의 정적 변수와 정적 메서드를 사용하고 있는 것을 볼 수 있음
    • model 인스턴스 변수와 printTest2() 인스턴스 메서드는 정적 멤버가 아니므로 사용할 수 없다!

지역 내부 클래스

  • 클래스의 멤버가 아닌 메서드 내에서 정의되는 클래스
  • 지역 변수와 유사하게 메서드 내부에서만 이용 가능 -> 일반적으로 메서드 안에서 선언 후 바로 객체를 생성해 이용
profile
자바, 웹 개발을 열심히 공부하고 있습니다!

0개의 댓글