접근 제어자
클래스에서
public, default 두 가지만 사용 가능하다.
public을 지우면 default가 되며 같은 패키지 안에서만 접근이 가능해진다.
메소드에서
public, protected, default, private 네 종류 모두 사용 가능하다.
기본적으로는 private로 작업하게 된다.
접근 제어자 | 접근 범위 | 클래스 | 패키지 | 상속 | 전체 |
public | 접근 제한 없음 | ○ | ○ | ○ | ○ |
protected | 동일 패키지와 상속받은 클래스 | ○ | ○ | ○ | |
default | 동일 패키지 | ○ | ○ | ||
private | 클래스 | ○ |
Static
class Player {
private String name;
private int count; // 기본 초기값 0
public Player(String name) {
this.name = name;
count++; // count 1 증가
}
public int getCount() {
return count;
}
}
public class StaticModifierRunner {
public static void main(String[] args) {
Player player1 = new Player("Kim");
System.out.println(player1.getCount()); // 1 출력
Player player2 = new Player("Lee");
System.out.println(player2.getCount()); // 1 출력
}
}
Player 클래스와 main 메서드가 들어갈 Runner 클래스를 각각 만들어주었다.
이렇게 만들어진 인스턴스 player1, player2는 각각의 count를 갖기에 (player1의 count / player2의 count) 각자가 자신의 count를 1씩 증가시킨 상태이다. 따라서 각각 1이 출력되게 된다.
모든 인스턴스 사이에서 공유되는 변수를 만들고 싶은 경우
여기서 player1.getCount() 을 실행하면 count++로 인해 count가 1 증가되고, 이 변수가 그대로 player2에게 값으로 부여되어 이후 player2.getCount() 을 실행하면 count가 1 증가되어 2가 되기를 원한다고 하자. 이는 즉 count가 모든 인스턴스 사이에서 공유되었으면 한다는 뜻이다.
이 경우 static을 이용해 다수의 인스턴스 사이에서 공유되는 변수를 만들 수 있다.
class Player {
private String name;
private static int count = 0; // static 변수
public Player(String name) {
this.name = name;
count++;
}
public int getCount() {
return count;
}
}
public class StaticModifierRunner {
public static void main(String[] args) {
Player player1 = new Player("Kim");
System.out.println(player1.getCount()); // 1 출력
Player player2 = new Player("Lee");
System.out.println(player2.getCount()); // 2 출력
}
}
이렇게 static을 붙여주면 Player 클래스의 모든 인스턴스와 공유되는 count 변수를 선언해줄 수 있다.
여러 인스턴스들이 같은 클래스의 자료를 공유해야하는 경우 유용하게 사용할 수 있다.
Static 메서드 콜은 클래스명으로
위 코드를 보면 player1.getCount() 라고 호출한 것을 알 수 있는데, count는 사실 player1보다는 Player 클래스와 관련이 있는 변수이다. player1의 count와 player2의 count는 모두 Player 클래스의 count를 공유하고 있기 때문이다.
따라서 아래와 같이 코드를 변경해줘야 한다.
class Player {
private String name;
private static int count = 0;
public Player(String name) {
this.name = name;
count++;
}
static public int getCount() { // static으로 변경. 이 메서드는 static 변수에만 접근한다
return count;
// System.out.println(name); <- 불가. name은 멤버 변수라서.
}
}
public class StaticModifierRunner {
public static void main(String[] args) {
Player player1 = new Player("Kim");
System.out.println(Player.getCount()); // 1 출력
Player player2 = new Player("Lee");
System.out.println(Player.getCount()); // 2 출력
}
}
Player.getCount() 처럼 메서드 콜을 위해 클래스명을 사용한다는 것은 지금 부르는 메서드가 static 메서드임을 알려준다.
static 메서드는 static 변수만 접근 가능
- static 메서드는 객체가 생성되지 않은 상황에서도 사용이 가능하다.
- new 로 인스턴스를 만들어주지 않아도, 이미 static 메서드가 클래스의 메모리에 올라가 있다.
- static 메서드는 클래스 레벨의 메서드이다.
- 클래스 레벨 메서드 안에서는 인스턴스 데이터에 접근을 시도하는 것 자체가 불가능하다. 그러므로 static 메서드 내부에 System.out.println(name) 을 사용하는 것은 불가능하다. 그러나 non-static 메서드와 인스턴스 메서드에서는 접근이 가능하다.
- static 메서드는 클래스 레벨의 메서드이다.
- 따라서 객체에 속한 인스턴스 메소드, 인스턴스 변수 등을 사용할 수 없다.
- new 로 인스턴스를 만들어주지 않아도, 이미 static 메서드가 클래스의 메모리에 올라가 있다.
REF
https://www.youtube.com/watch?v=SX9mEozLqsc