생성자, 접근 제어자, package와 import

star_pooh·2024년 11월 13일
0

TIL

목록 보기
17/39
post-thumbnail

생성자

객체가 생성될 때 호출되며 객체를 초기화하는 역할을 수행

  • 생성자 선언과 호출
    • 리턴 타입이 없고 생성자명은 클래스의 이름과 동일
    • new 연산자에 의해 객체가 생성되면, 생성자가 호출됨
  public Car() {} // 선언
  Car car = new Car(); // 호출

기본 생성자

선언할 때 괄호 안에 아무 것도 넣지 않은 생성자

  • 모든 클래스는 반드시 생성자가 하나 이상 존재
  • 클래스에 생성자를 하나도 선언하지 않았다면, 컴파일러가 기본 생성자를 자동으로 추가(따라서, 기본 성성자는 생략이 가능)
  • 하나라도 생성자가 선언되어 있다면, 컴파일러는 기본 생성자를 추가해주지 않음
  • 컴파일러에 의해 생성되는 기본 생성자는 해당 클래스의 접근제어자를 따름
public class Car {
	public Car(String model) {} // 생성자 선언
	// 생성자가 한개 이상 선언되었기 때문에 기본 생성자를 추가하지 않음
}
public class Car {
    // 컴파일러가 추가시켜준 기본 생성자라면
    // 접근제어자는 클래스와 같은 public
    public Car() {}
}

필드 초기화와 생성자 오버로딩

  • 생성자는 객체를 초기화하는 역할을 수행하기 때문에 객체를 만들 때 인스턴스마다 다른 값을 가져야 한다면, 생성자를 통해서 필드를 초기화할 수 있음
  • 인스턴스마다 동일하나 데이터를 가지는 필드가 있다면, 초기값을 대입하는 것이 좋음
  • 필드값을 초기화하는 생성자 만들었다면 기본 생성자 호출 시 에러 발생(생성자가 존재하여 컴파일러가 기본 생성자를 만들어 주지 않기 때문에)
public Car(String modelName, String colorName, double priceValue) {
    model = modelName;
    color = colorName;
    price = priceValue;
}
...
Car car = new Car(); // 에러 발생
  • 생성자를 통해 필드를 초기화할 때 오버로딩 적용 가능
// 오버로딩 시에는 매개변수 개수, 타입, 순서 중요
public Car(String modelName, String colorName) {}
public Car(String modelName, String colorName, double priceValue) {}

this와 this()

  • this는 객체 즉, 인스턴스 자신을 표현
  • 객체 내부 생성자 및 메소드에서 객체 내부 멤버에 접근하기 위해 사용
public Car(String model, String color, double price) {
    model = model;
    color = color;
    price = price;
}
  • 위의 예시처럼 생성자를 선언했다면 에러가 발생하지는 않지만, 생성자 블록 내부에서 해당 변수들은 객체의 필드가 아닌 가장 가까운 매개변수명을 가리키게 됨으로 자기 자신에게 값을 저장하게 됨
public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}
  • 이럴 경우 this를 통해 객체의 필드에 접근하고 매개변수의 값을 객체의 필드에 저장 가능
  • 객체의 메소드에서 리턴 타입이 인스턴스 자신의 클래스 타입이라면 this를 사용하여 자신의 주소를 리턴할 수도 있음
Car returnInstance() {
    return this;
}
  • this()는 객체 즉, 인스턴스 자신의 생성자를 호출
  • 객체 내부 생성자 및 메소드에서 해당 객체의 생성자를 호출하기 위해 사용될 수 있으며, 생성자를 통해 객체의 필드를 초기화할 때 중복되는 코드를 줄일 수 있음
// this() 사용 전
public Car(String model) {
    this.model = model;
    this.color = "Blue";
    this.price = 50000000;
}

public Car(String model, String color) {
    this.model = model;
    this.color = color;
    this.price = 50000000;
}

public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}
👇
// this() 사용 후
public Car(String model) {
    this(model, "Blue", 50000000);
}

public Car(String model, String color) {
    this(model, color, 100000000);
}

public Car(String model, String color, double price) {
    this.model = model;
    this.color = color;
    this.price = price;
}

⚠️ 단, this()를 사용해서 다른 생성자를 호출할 때는 반드시 첫 줄에 작성되어야 함

public Car(String model) {
	// this()가 첫 줄이 아니기 때문에 에러 발생
    System.out.println("model = " + model);
    this(model, "Blue", 50000000);
}

접근 제어자

  • 제어자는 클래스, 변수, 메소드의 선언부에 사용되어 부가적인 의미를 부여
    • 접근 제어자 : public, protected, default, private
    • 그 외 제어자 : static, final, abstract
      ⚠️ 여러 개의 제어자를 조합해서 사용할 수 있으나, 접근 제어자는 단 하나만 사용 가능
  • 캡슐화(은닉성)
    • 클래스 내부에 선언된 데이터를 보호하기 위해 사용
    • 유효한 값을 유지하고 함부로 변경하지 못하도록 접근을 제한
  • 멤버 또는 클래스에 사용하여 외부에서의 접근을 제한함
  • 클래스, 멤버 변수, 메소드, 생성자에 사용되며 지정하지 않는다면 default가 지정됨
    - public : 접근 제한이 없음(누구나 접근 가능)
    - protected : 같은 패키지 내 또는 다른 패키지의 자손 클래스에서 접근 가능
    - default : 같은 패키지 내에서만 접근 가능
    - private : 같은 클래스 내에서만 접근 가능

  • 사용 가능한 접근 제어자를 분류하면 아래와 같음
    • 클래스 : public, default
    • 메소드, 멤버변수 : public, protected, default, private
    • 지역변수 : 없음

Getter와 Setter

Getter : 외부에서 객체의 private한 필드를 읽을 필요가 있을 때 사용
Setter : 외부에서 객체의 private한 필드에 데이터를 저장/수정할 필요가 있을 때 사용

  • getter의 경우 메소드명을 get + 필드명으로 지정
  • setter의 경우 메소드명을 set + 필드명으로 지정
  • 사용 방법은 인스턴스 메소드 호출과 동일
private String speed;
private double price;
// Getter
public String getSpeed() {
    return speed;
}

public double getPrice() {
    return price;
}
// Setter
public String setSpeed(String speed) {
    this.speed = speed;
}

public double setPrice(double price) {
    this.price = price;
}

제어자의 조합

  • 사용 가능한 제어자
    • 클래스 : public, default, final, abstract
    • 메소드 : public, protected, default, private, final, abstract, static
    • 멤버 변수 : public, protected, default, private, final, static
    • 지역변수 : final

package와 import

패키지는 클래스의 일부분이며 클래스를 식별해주는 용도

  • 패키지는 상위 패키지와 하위 패키지를 도트(.)로 구분
  • package 상위 패키지.하위 패키지;로 선언
package oop.pk1;

public class Car {
    public void horn() {
        System.out.println("pk1 빵빵");
    }
}
package oop.pk2;

public class Car {
    public void horn() {
        System.out.println("pk2 빵빵");
    }
}
package oop.main;

public class Main {
    public static void main(String[] args) {
    	// pk1과 pk2 모두 Car 클래스를 가지고 있는 경우, 패키지의 경로로 구분
        oop.pk1.Car car = new oop.pk1.Car();
        car.horn(); // pk1 빵빵

        oop.pk2.Car car2 = new oop.pk2.Car();
        car2.horn(); // pk2 빵빵
    }
}

import는 다른 패키지에 있는 클래스를 사용하기 위해 명시하는 키워드

  • import 다른 패키지에 있는 클래스의 경로로 선언
  • *을 사용하면 패키지 안에 있는 모든 클래스 사용 가능
package oop.main;

import oop.pk1.Car;
// import oop.pk1.*; // pk1의 패키지에 있는 모든 클래스 사용 가능

public class Main {
    public static void main(String[] args) {
        Car car = new Car();
        car.horn(); // pk1 빵빵

        oop.pk2.Car car2 = new oop.pk2.Car();
        car2.horn(); // pk2 빵빵
    }
}

0개의 댓글

관련 채용 정보