Java의 제어자는 클래스나 클래스 변수(멤버 변수, 메서드)의 선언부에 함께 사용하여 부가적인 의미를 부여한다.
분류 | 항목 |
접근 제어자 | public, protected, (default), private |
그외 | static, final, abstract, native, trasient, synchronized, volatile, strictfp |
접근 제어자
외부로부터 데이터를 보호하기 위해서 사용하는 제어자로, 내부적으로만 사용되는 부분을 감추기 위해서 사용한다.
접근 범위 | 제어자 | 사용될 수 있는 곳 | 대상 |
좁음 넓음 |
private | 같은 클래스 내 접근 가능 | 메서드, 멤버변수 |
(default) | 같은 패키지 내 접근 가능 | 클래스, 메서드, 멤버변수 | |
protected | 같은 패키지 내, 다른 패키지의 자손클래스에서 접근 가능 | 메서드, 멤버변수 | |
public | 접근 제한 없음 | 클래스, 메서드, 멤버변수 |
package com.example1;
public class Modifier {
private int a = 1;
int b = 2;
protected int c = 3;
public int d = 4;
public static void main(String[] args) {
Modifier mod1 = new Modifier();
System.out.println(mod1.a); //1
System.out.println(mod1.b); //2
System.out.println(mod1.c); //3
System.out.println(mod1.d); //4
}
}
package com.example1;
public class ModifierEx_samePkg {
public static void main(String[] args) {
Modifier mod1 = new Modifier();
// System.out.println(mod1.a); // 에러
System.out.println(mod1.b); //2
System.out.println(mod1.c); //3
System.out.println(mod1.d); //4
}
}
package com.example2;
import com.example1.Modifier;
public class ModifierEx_diffPkg {
public static void main(String[] args) {
Modifier mod1 = new Modifier();
// System.out.println(mod1.a); // 에러
// System.out.println(mod1.b); // 에러
// System.out.println(mod1.c); // 에러
System.out.println(mod1.d); //4
}
}
생성자의 접근 제어자
생성자의 접근 제어자를 사용함으로써 인스턴스의 생성을 제한할 수 있다. private 접근 제어자를 사용할 경우, 인스턴스의 생성을 방지할 수 있다. 대신 해당 클래스 내부에서 인스턴스를 생성하고, public 메서드를 제공하여 외부에서 해당 메서드를 통해서만 접근할 수 있도록 제한할 수 있다. * 싱글톤 패턴 : 메모리 절약을 위해 기존의 인스턴스를 가져와 활용할 수 있도록 하는 패턴
package com.example1;
public class Example1 {
public static void main(String[] args) {
// Singleton s = new Singleton(); 외부에서 생성자에 접근할 수 없어서 불가능
// getInstance() 메서드를 통해서 클래스의 인스턴스를 사용한 후에,
Singleton s = Singleton.getInstance();
// protected 메서드를 호출해서 사용할 수 있다.
s.method1(); // method1 호출
}
}
// 생성자가 private인 경우 다른 클래스의 조상이 될 수 없기 때문에 클래스 앞에 final을 추가하여 알린다.
final class Singleton {
//private 지정하게 되면 외부에서 생성자에 접근할 수 없음, 클래스 내부에서는 인스턴스 생성가능
// getInstance()에서 사용될 수 있도록 인스턴스가 미리 생성되어야 하므로 static 이어야 함 (인스턴스 생성하지않아도 사용가능)
private static Singleton s = new Singleton();
private Singleton() {
}
protected void method1() {
System.out.println("method1 호출");
}
//클래스내부에서 인스턴스를 생성할 수 있기 때문에, 인스턴스를 생성해서 반환해주는 public 메서드 사용
public static Singleton getInstance() {
if (s == null)
s = new Singleton();
return s;
}
}
그외
Static
static은 인스턴스가 아닌 클래스에 관계된 키워드로, 인스턴스를 생성하지 않아도 사용이 가능하다. Static는 JVM의 클래스 영역(Method Area)에 적재되어 메모리가 로딩될 때 로드되어 프로그램이 종료할 때까지 유지된다. 따라서 갱신이 없는 데이터, 모든 인스턴스에서 공유해야 하는 공통적인 값을 저장할 때 유용하다.
static 변수
모든 인스턴스에서 공통적으로 사용되는 클래스 변수로, 객체를 생성하지 않고 '클래스이름.변수명'으로 호출이 가능하다.
static 메서드
인스턴스를 생성하지 않고도 호출이 가능한 static 메서드로, static메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다. 객체를 생성하지 않고 '클래스이름.메서드명()'으로 호출이 가능하다.
package com.example1;
public class Example1 {
// static 멤버변수
public static int a = 100;
// static 메서드
public static void setA1(int a){
Example1.a = a;
}
}
package com.example1;
public class Example1_1 {
public static void main(String[] args) {
//따로 인스턴스를 생성하지 않아도 변수와 메서드를 불러올 수 있다.
System.out.println(Example1.a); // 100
Example1.setA1(200);
System.out.println(Example1.a); // 200
}
}
Final
클래스, 메서드, 멤버변수 및 지역변수를 바꿀 수 없도록 할 때 쓰인다.
final 클래스
확장될 수 없는 클래스가 되어, 다른 클래스의 조상이 될 수 없다.
final 메서드
변경될 수 없는 메서드로, 오버라이딩을 통해 재정의 될 수 없다.
final 변수 (멤버변수, 지역변수)
처음 선언한 값을 변경할 수 없는 상수가 된다. 상수의 경우 영어 대문자로 작성한다.
final class FinalTest {
final int MAX_SIZE = 10; // 변경할 수 없는 멤버 변수
final int getMaxSize() { // 오버라이딩할 수 없는 메서드
final int LV = MAX_SIZE; // 변경할 수 없는 지역 변수
return MAX_SIZE; // MAX_SIZE 반환
}
}
Abstract
Abstract의 경우 여러 클래스에서 사용될 수 있는 부분을 공통적인 특성을 클래스로 묶고, 특성 메서드의 구현을 자식 클래스에 맡길 때 사용하는 제어자이다.
Abstract 클래스 (추상 클래스)
클래스 내에 하나 이상의 추상 메서드가 선언되었음을 의미한다. 즉, 전체적인 구성을 다 가지지 못한 채 설계만 되어 있는 미완성 클래스이다. Abstract 클래스는 인스턴스 생성이 불가능하며, 상속을 통해서 완전한 클래스를 만든 후에 객체 생성이 가능하다.
- 접근자 abstract class 클래스명 {}
Abstract 메서드
선언부(메서드 명, 매개변수, 반환값)만 작성하고 구현부는 작성하지 않은 메서드로, 클래스 상속 후에 오버라이딩을 통해서 완성되어야 한다.
- 접근자 abstract 리턴타입 메서드명();
package com.example1;
// 추상클래스
abstract class Ride {
// 추상메서드
abstract void move();
}
package com.example1;
// Ride를 상속받는다.
public class Car extends Ride {
// Ride의 추상메서드를 오버라이딩을 통해 구현한다.
@Override
void move() {
System.out.println("자동차를 탄다.");
}
public static void main(String[] args) {
Car car1 = new Car();
car1.move(); // 자동차를 탄다.
}
}
제어자의 조합
대상 | 사용가능한 제어자 |
클래스 | public, (default), final, abstract |
메서드 | 모든 접근제어자(private, (default), protected, public), final, static, abstract |
멤버변수 | 모든 접근제어자, final, static |
지역변수 | final |
- 메서드에 static과 abstract을 같이 사용할 수 없다. static메서드는 몸통이 있는 메서드만 가능하다.
- 클래스에 abstract과 final 동시에 사용할 수 없다. abstract경우 상속을 통해서만 완성되기 때문에, 상속이 불가능한 final 사용이 불가능하다.
- abstract 메서드의 접근제어자가 private일 수 없다. abstract의 경우 상속을 통해서만 완성되기 때문에, 상속이 불가능한 private와 같이 사용될 수 없다.
- 메서드에 private과 final을 같이 사용할 필요가 없다. 둘 중 하나만 작성해도 의미를 전달하는데 충분하다.
'Backend > Java' 카테고리의 다른 글
JAVA : 레코드(Record)에 대해서 (0) | 2024.10.07 |
---|---|
Java 기초 문법 : JVM 메모리구조 (0) | 2024.10.07 |
Java 기초 문법 : 인터페이스(interface) (1) | 2024.06.19 |
Java 기초 문법 : 다형성(polymorphism) (0) | 2024.06.13 |
Java 기초 문법 : 패키지, import문 (1) | 2024.06.13 |
Java 기초 문법 : this와 super() (0) | 2024.06.10 |
Java 기초 문법 : 클래스간의 관계 - 상속과 포함 (0) | 2024.06.09 |
Java 기초 문법 : 오버로딩에 대해서 (0) | 2024.05.26 |