접근 지정자와 static 정리

Haiseong Jeong·2022년 9월 30일
3
post-thumbnail

항상 헷갈리는 것

맞춤법은 항상 헷갈린다. 접근 지정자와 static은 항상 헷갈린다. 나만그럼? 그래서 이참에 블로그에 정리하면서 공부하고 다시는 헷갈리지 않겠다고 결심했다. 물론 본인은 두개념을 혼동하는게 아니라 각각 헷갈린다는 의미였다. 오해 ㄴㄴ

매일 사용하는 main 메서드

자바 클래스를 만들면 너무나 당연하게 main 메소드 안에 코딩을 시작한다. C언어를 사용한 사람이라면 이와 비슷하게 int main() 라는 메인함수를 만들고 코딩을 시작할 것이다. 그래, void는 반환값이고 publicstatic은 왜붙어 있는건가 궁금해 본적이 있는가? 먼저 접근 지정자인 public부터 알아보자

자바의 접근 지정자 4가지

자바는 4가지 접근 지정자가 있다.

public, protected, default, private

이름에서도 감이 오듯이 public이 외부에서 접근하기 좋고 private는 외부접근이 불가능 해 보인다. 맞다.

접근 지정자는 다음 위치에 사용 가능하다.

Class에 사용 가능
public, default
Construtor
public, protected, default, private
Member 변수
public, protected, default, private
Member method
public, protected, default, private
지역 변수
접근 제한자 사용 불가

public

private와 함께 가장많이 사용되는 지정자 이다. 다른 모든 클래스에게 접근허용을 해준다.

protected

protected는 같은 패키지와 자식 클래스에 사용을 허용해준다.

default

아무것도 쓰지 않으면 default이다. default는 동일 패키지에서 사용가능하다. 참고로 패키지는 그냥 같은 폴더(디렉토리)라고 생각하면 편하다.

private

public과 함께 가장많이 사용되는 지정자 이다. 클래스 안에서만 사용이 가능하다.

protected는 왜써?

처음 보면 애매하다. 같은 패키지에서 쓸려면 default를 쓰면되고 상속을 받으면 public과 비슷하다. 본인도 아직 감을 잘 못잡았지만 다른 블로그들을 찾아보면서 쓰는 이유를 찾았다. 메소드

protected 는 잠재적으로 자식 클래스가 Override해서 바꾸어야 할 경우를 고려한 modifier이다. 즉 완성되지 못한, 혹은 완성될 수 없는 클래스 멤버를 의미한다. 여기서 "완성되지 못한/ 완성될 수 없는"의 의미가 중요하다. 클래스를 디자인한 개발자가 이 메소드에 대해서 앞으로 더 구현할 것이 남았다거나, 혹은 디자인 컨셉트로서 일부러 완성시키지 않은 경우 둘 다를 의미할 수 있다.
출처 : https://m.blog.naver.com/2feelus/220576845725

public으로 된 메소드는 그대로 그냥 써도 충분한 이미 완성된 메소드를 의미한다. protected의 경우는 자식 클래스의 특성에 따라 적절히 변경해주어야 하는 상황을 고려한 메소드이다. 위의 블로그의 예시를 그대로 가져오겠다.

Bird Class

public class Bird{
   void fly() {
       System.out.println("I am flying");
   }
   
   protected void moveFast() {
      fly();
   }
}

Ostrich Class

public class Ostrich extends Bird {
	public static void main(String[] args) {
		Ostrich  ostrich = new Ostrich();
		ostrich.moveFast();
	}
	
	void run() {
	   System.out.println("I am running");
	}
	
	protected void moveFast() {
		run();
	}
}

새를 의미하는 public 클래스인 Bird 클래스가 있다. 우리는 타조를 의미하는 Ostrich 클래스를 만드는중이다. 타조는 새에 포함되기 때문에 Bird 클래스를 상속받는다. 그러나 여기서 문제가 생긴다.

일반적인 새와 다르게 타조는 날지 못한다. 따라서 타조는 fly 메소드를 사용할 수 없다. 따라서 moveFast 메소드도 사용이 불가능 하다. 그런데 여기서 moveFast 메소드 앞에 붙어있는 protected를 발견한다. 우리의 훌륭하신 선배 개발자께서 이 상황을 미리 예측한 것이다. (날지 못하는 새가 있을지 모르니 메서드를 수정할 가능성이 있다는 것을 알려줘야겠군 이라고..)

정리해보면 사실 내가 클래스를 만들어서 사용하려면 protected를 쓸 이유가 없다. 하지만 다른 사람이 이 클래스를 쓸거라고 생각한다면 이 부분을 신경써봐야 할것이다.

static

static은 '정적인'이라는 의미이다. 이는 고정되었다는 뜻이다. static 키워드를 멤버변수에 붙이면 static member (정적 필드)라 하고, 맴버메소드에 붙이면 static method (정적 메소드) 라고 한다. 고정되어있다는 것은 각 객체인 인스턴스에 소속된것이 아니라 클래스에 고정되어 공유된다는 뜻이다.

static member

class Number{
    static int num = 0;
}

public class Test {
    public static void main(String[] args) {
    	Number number1 = new Number(); //첫번째 number
    	Number number2 = new Number(); //두번쨰 number
    	
    	number1.num++; //클래스 필드 num을 1증가시킴
    	System.out.println(number2.num); // 출력 : 1
    }
}

Number 인스턴스를 두개 설정한다. number1.num을 1증가시키고 number2.num을 출력하면 1이 출력된다. 이는 num을 정적 필드로 선언했기 때문이다. 정적 필드는 객체인 인스턴스에 소속된것이 아니라 클래스에 고정되어 공유되기 때문이다.

이런 특성 때문에 static member를 마치 전역변수처럼 쓰는 경우가 많다.

static method

정적 메소드는 클래스가 메모리에 올라갈 때 자동적으로 생성된다. 이는 따로 인스턴스를 만들지 않아도 메소드를 사용할 수 있다는 의미이다. 다음은 정적 메소드를 사용해야 하는 경우를 정리한 블로그 인용글이다.

  1. 만약 유틸리티 클래스로 작성되고, 변화를 가정하지 않는다.
  2. 만약 메소드가 인스턴스 변수를 사용하지 않는다.
  3. 인스턴스 생성에 의존하지 않는다.
  4. 메소드가 공유되고 있다면, 정적 메소드로 추출해낼 수 있다.
  5. 메소드가 변화되지 않고, 오버라이딩 되지 않는다.
    출처 : https://mygumi.tistory.com/253

static 키워드의 문제

static 키워드를 배웠으니 이제 열심히 써봐야 겠다고 하기 전에 생각해볼게 있다. static 키워드의 문제점이다. static 키워드는 절차지향적 언어에 가까운 키워드이다. 객체지향적인 특성을 망가트릴 수 있다. 그러므로 사용하기전에 신중해야한다. 쓰지말라는 이야기가 아닌 써야할 상황을 잘 판단해서 신중히 써야한다는 이야기다.

public static void main()

자 이제 메인 메서드의 앞에 왜 이 두 키워드가 붙어있는지 이해가 되는가? main 메소드는 모든 실행프로그램의 기본이 된다. 따라서 어디서나 실행이 가능해야한다. 따라서 public을 붙여준다. 그리고 main 메소드는 객체를 만들어서 실행되지 않는다. 객체를 만들지 않고도 실행되도록 static을 붙여줘야한다.

profile
나는 개발자다. 5000만큼 코딩한다.

0개의 댓글