제어자란?

제어자(modifier)는 변수와 메서드의 선언부에 함께 사용되어 부가적인 의미를 나타낸다.

제어자는 2가지 종류로 나뉜다.

  • 접근제어자
    • public, protected, default, private
  • 접근제어자 외의 것들
    • static, final, abstract, native, transient, synchronized, volatile, strictfp

제어자는 하나의 대상에 하나만 쓸수 있는 것이 아니라 하나의 대상에 대해서 여러 제어자를 조합하여 사용하는 것이 가능하다.

Static

static클래스의 라는 의미와 공통적인이라는 의미를 가지고 있다.

이러한 static이 붙은 메서드나 맴버변수는 인스턴스에 관계없이 같은 값을 가진다

static멤버변수, 메서드, 초기화 블럭에 사용된다.

static(클래스 변수) 와 인스턴스 변수의 차이점이 궁금하다면 이곳에 자세히 나와있다.

  • 멤버변수에서 사용이 되면 클래스변수가 되어서 모든 인스턴스에서 공통적으로 사용할 수 있다. 또한, 인스턴스를 생성하지 않고도 사용이 가능하다.
  • 메서드에서 사용이 되면 인스턴스를 생성하지 않고도 호출이 가능하다. 또한, static메서드 내에서 인스턴스 멤버들을 직접 사용할 수 없다.

Final

final은 마지막의 또는 변경될 수 없는이라는 의미를 가지고 있다.

final도 2장의 상수를 다루면서 설명하였다. 설명

final클래스, 메서드, 멤버변수, 지역변수에서 사용할 수 있다.

  • 클래스에서 사용이 되면 확장 될 수 없는 클래스가 된다. 그래서 다른 클래스의 부모클래스가 될 수 없다.
  • 메서드에서 사용이 되면 오버라이딩을 통해 재정의 될 수 없다.
  • 변수에서 사용이 되면 값을 변경할 수 없는 상수가 된다.

final은 항상 선언과 동시에 초기화를 하는 변수이다.

하지만 인스턴스변수인 경우는 생성자에서 초기화를 할 수 있다.

class Car {
    final String NAME;

    Car(String name){
        NAME = name;
    }
}

생성자를 사용하면 인스턴스마다 각기 다른값을 final로 가지게 할 수 있다.

Abstract

abstract미완성의 의미를 가지고 잇다. abstract가 붙으면 추상이라는 말이 따라온다.

abstract클래스메서드에 사용이 가능하다.

abstract클래스에 붙으면 추상클래스라고 말하고 이는 설계도에 비유하면 미완성 설계도라고 만 알고가자

추상클래스는 나중에 따로 작성할 것이다.

abstract메서드에 붙으면 추상메서드라고 말하고 이는 이러이러한 기능이 있다는 것만 설명하고 기능을 구현을 하지 않은 것이다.

선언부는 작성되어있지만 구현부는 작성이 되지 않은 것이다.

abstract class Car{
    abstract void move();
}

이는 아무런 구현이 없어 쓸모없어 보이지만 이 클래스를 상속받는 클래스에게 원하는 기능을 오버라이딩을 해야한다

접근 제어자 (access modifier)

접근 제어자는 멤버 또는 클래스에 사용하여 이를 외부에서 접근하지 못하도록 제한하는 역할을 한다.

접근 제어자의 종류는 다음과 같다.

  • private : 같은 클래스 내에서만 접근이 가능하다.
  • default : 같은 패키지 내에서만 접근이 가능하다.
  • protected : 같은 패키지 안에서 그리고 다른 패키지의 자손클래스에서 접근이 가능하다.
  • public : 모두 접근이 가능하다.

넓은쪽 에서 좁은 쪽 순서로는 다음과 같다.

public > protectd > (default) > private

캡슐화(encapsulation)

접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서이다.

이를 보통 캡슐화라고 한다.

또한, 클래스 내부에서만 사용하는 맴버들을 private로 지정하여 외부에 노출시키지 않음으로 복잡성을 줄이는 것 또한 캡슐화라고한다.

캡슐화된 값들을 사용하기 위해서는 Getter/Setter라는 메소드를 이용하여 값을 접근한다.

class Car{
    private String name;

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

Getter는 멤버 변수의 값을 반환하는 역할을 한다.

Setter는 멤버 변수의 값을 설정하는 역할을 한다.

Singleton 패턴

Singleton은 디자인 패턴줄하나로 인스턴스를 단 하나만 생성할 수 있게 하는 방법이다.

이는 생성자에 접근 제어자를 사용하는 방식으로 이루어져있다.

생성자의 접근 제어자를 private 로 지정한다면 외부에서 생성자에 접근할 수 없으므로 인스턴스를 생성할 수 없게 된다.

class Car{
    private static Car car = new Car(); // static을 사용

    private Car(){
        /...
    }

}

public static void main(String[] argc){
        Car car = new Car() // -> 불가능 Car()는 private이기 때문이다.
}

생성자가 private이기 때문에 더이상의 인스턴스를 생성할 수 없다.

private이기 때문에 인스턴스에 접근조차 할수가 없다. 그러므로 class 안에서 생성된 인스턴스를 불러올 방법을 찾아야한다.

// 해결방법
class Car{
    private static Car car = new Car(); // static을 사용

    private Car(){
        /...
    }

    public static Car getInstance(){
        return car;
    }
}

getInstance() 메서드를 사용하여 미리생성된 car인스턴스를 반환한다.

또한, static으로 생성되었기 때문에 main함수에서 접근이 가능하다.

이는 생성자가 private이기 때문에 다른 클래스의 조상이 될 수 없다.

이러한 싱글톤 패턴에는 문제점이있다.

  • 단 하나의 인스턴스를 사용하기 때문에 동시에 객체의 변수를 변경하고 요청한다면 오류가 생길 수 있다.
  • 싱글톤 패턴을 구현하는 코드 자체가 많이들어간다.
  • private생성자 이기때문에 자식을 만들기가 어려워진다.

이러한 문제점들이 존재한다.

제어자의 조합

제어자는 조합이 가능한데 마음대로 쓸수 있는 것들은 아니다.

제어자는 다음과 같은 사항을 준수해야한다.

  1. 메서드에 staticabstract를 함께 사용할 수 없다.
    • abstract는 메서드를 구현하지 않지만 static은 메서드 구현이 필요하기 때문이다.
  2. 클래스에 abstractfinal을 동시에 사용할 수 없다.
    • abstract는 항상 상속을 받아야한다는 의미이다. 하지만 final은 클래스에서 상속을 받을수 없다는 의미 이기 때문에 서로 상반된다.
  3. abstract메서드의 접근 제어자가 private 일 수 없다.
    • abstact는 상속을 받아서 자식클래스에서 구현이 되야한다. 하지만 private일 때는 자식클래스에서 abstact메서드를 접근할 수 없기 때문이다.
  4. 메서드에 privatefinal을 같이 사용할 필요는 없다.
    • privatefinal을 쓰면 서로 의미가 같아져서 하나만 써도 의미가 충분하다. (메소드의 오버라이딩 금지)

Reference

  • 자바의 정석

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

[Java/Study] 추상클래스  (0) 2021.09.11
[Java/Study] 다형성  (0) 2021.09.10
[Java/Study] Package 와 Import 및 터미널로 자바 실행방법  (0) 2021.09.08
[Java/Study] 오버라이드  (0) 2021.09.07
[Java/Study] 상속  (0) 2021.09.07

+ Recent posts