반응형
매일 public과 private 제어자를 사용해 클래스나 메서드를 선언하는데, 이 둘을 주로 사용하다보니 다른 접근 제어자인 protected, default가 헷갈리기 시작해 정리하는 글이다.
이왕 정리하는 김에 접근 제어자 뿐만 아니라 그 외의 제어자에 대해서도 간략히 정리해보고자 한다.
제어자(modifier)란?
- 클래스, 변수 또는 메서드의 선언부에 사용돼 부가적인 의미를 부여한다.
- 종류
- 접근 제어자 : public, protected, default, private
- 그 외 제어자 : static, final, abstract, native, transient, synchronized, volatile, strictfp
- 하나의 클래스나 멤버변수, 메서드 등의 대상에 대해서 여러 제어자를 조합해 사용하는 것이 가능하다.
- 단, 접근 제어자는 상기에 적은 4가지 중 단 하나만 사용할 수 있다.
- 여러 제어자를 조합해 사용할 때 순서를 상관 없지만 주로 접근 제어자를 가장 먼저 쓴다.(ex: private static testVariable ..)
바로 이어서 접근 제어자 이외의 제어자부터 살펴보도록 한다.
여기서는 대표적으로 많이 사용되고, 자주 볼 수 있는 static, final, abstract 제어만 살펴본다.
static
- 의미 : 클래스의, 공통적인
- static이 붙은 멤버변수, 메서드, 초기화 블럭은 인스턴스가 아닌 클래스에 관계된 것이기 때문에 인스턴스를 생성하지 않고 사용 가능하다.
- 클래스 변수(static 멤버변수)
- 하나의 변수를 모든 인스턴스가 공유하기 때문에 인스턴스에 관계없이 같은 값을 갖는다.
- 클래스가 메모리에 로드될 때 생성된다.
- static 메서드
- static 메서드 내에서는 인스턴스 멤버들 직접 사용 불가능하다.
final
- 의미 : 마지막의, 변경될 수 없는
- final 변수 : 값을 변경할 수 없는 상수가 된다.
- final 메서드 : 오버라이딩을 통해 재정의 될 수 없다.
- final 클래스 : 확장될 수 없는 클래스가 되어 자손클래스를 정의하지 못한다.
- 대표적인 final 클래스 : String, Math클래스
생성자를 이용한 final 멤버변수의 초기화
- final이 붙은 변수를 상수이기 때문에 일반적으로 선언과 초기화를 동시에 하지만, 인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있다.
- 즉, 클래스 내에서 매개변수를 갖는 생성자를 선언하고, 인스턴스를 생성할 때 final이 붙은 멤버변수를 초기화하는데 필요한 값을 생성자의 매개변수로부터 제공받으면 된다.
- 이를 통해 각 인스턴스마다 final이 붙은 멤버변수가 다른 값을 갖도록 하는 것이 가능하다.
아래 코드를 통해 살펴보자.
class ColorAndNum {
// 상수지만 선언과 함께 초기화하지 않고 생성자에서 초기화
final String COLOR;
final int NUMBER;
// 매개변수로 넘겨받은 값으로 COLOR와 NUMBER 초기화
ColorAndNum(String color, int number){
COLOR = color;
NUMBER = number;
}
}
class FinalColorAndNumTest {
public static void main(String args[]){
ColorAndNum cn = new ColorAndNum("black", 0);
}
}
abstract
- 의미 : 미완성
- abstract 메서드 : 메서드의 선언부만 작성하고 실제 수행내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.
- abstract 클래스 : 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
- 아직 완성되지 않은 메서드가 존재하므로 인스턴스를 생성할 수 없다.
- 추상 메서드를 선언해 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스로 '미완성 설계도'로 보면 된다.
추상 클래스 vs 인터페이스
여기서 함께 알고가면 좋은 것이 있다.
추상 클래스의 경우 interface와 비슷한 기능을 하는 듯 하면서도 또 달라서 예상 면접 질문에 항상 등장하곤 했다.
간단하게 정리하자면,
추상 클래스
- 추상 클래스에 선언된 메서드들은 자손 클래스에서 상속받아 구현한다.
- 추상 클래스에서 상속을 받아 그 기능을 이용하고, 확장시키는 것에 의미가 있다.
interface(인터페이스)
- 인터페이스를 구현하는 클래스에서는 인터페이스에 정의된 메서드를 하나도 빠짐없이 모두 구현해야 한다.
- 즉, 메서드의 구현에 강제성이 있고, 이를 통해 구현한 객체들에 대해 동일한 동작을 보장한다.
그렇다면 모든 메서드를 구현하고자 할 때는 인터페이스를, 구현의 강제성을 두지는 않지만 상속을 통해 구현체의 확장에 의미를 두고 싶다면 추상 클래스를 사용하면 될텐데 왜 2가지로 나뉘어져 있을까?
답은 Java는 다중 상속을 지원하지 않기 때문이다.
하지만 이와 달리 인터페이스는 여러 개의 인터페이스를 구현할 수 있다.
static, final, abstract 제어자를 설명하다가 추상 클래스와 인터페이스의 차이점에 대해서도 간단하게 정리해보았다.
우선 이 글에서는 여기까지 정리하도록 하고 이어지는 글에서 접근 제어자에 대해 정리하도록 하겠다.
반응형
'Java' 카테고리의 다른 글
[Java] 코드 특정 구간의 실행 시간 구하기 (0) | 2023.06.14 |
---|---|
[Java] HashMap에 특정 key가 존재하는지 확인하기 (0) | 2023.04.17 |
[Java] new ArrayList<>() 와 Arrays.asList() 차이점 및 비교 (0) | 2022.12.26 |
[Java] HashMap과 HashSet의 차이 (0) | 2022.12.23 |
[Java] 제어자(modifier) (2) - 접근 제어자, 그 외 제어자 (0) | 2022.08.06 |