실험실

실험일지3 - 당신은 static을 얼마나 알고 있나요?

Chemi___6_oj 2024. 9. 7. 23:11

안녕하세요 이번에는 static 에 대해 실험해보려고 합니다.

 

static 키워드 같은 경우에는 대부분 알고 있는 내용들은 생략해보려고 해요~ 그러다가 중간중간 상기할만한 개념이 있다면 중요성을 강조해보

 

Static 은 특정 인스턴스 타입에 속해있는 것이 아닌, 유형 그 자체에 속해있는 것을 의미합니다.

쉽게 설몀하면, 정의한 유형을 서로 공유할 수 있는 형태인 것이죠

 

같은 변수명으로 다른 클래스에서 static 변수 선언이 가능할까?

 

가능합니다. 각각 Worker의 salary, Boss의 salary로 저장되며 둘은 서로 공유되는 상태가 아닌 채로 메모리 영역에 저장됩니다. 

 

인스턴스를 여러개 생성하면, static 변수 선언이 공유될까?

됩니다. Worker의 static 변수가 객체간에 공유되어 객체를 2개 생성하니, salary값이 증가한 것을 확인할 수 있습니다. 

 

1. 객체의 생성과 상관 없이 독립적으로 사용되는 상황이나,

2. 이 값이 모든 객체에 공유되어야 하는 경우

 

이런 경우에는 이렇게 static 변수를 선언해서 사용할 수 있을 것입니다.

 

결국, static변수는 클래스에 종속적이기 때문에, 클래스 이름을 통해서 직접 접근이 가능합니다. 그래서 우리는 객체 참조가 필요하진 않습니다. (객체 초기화도 필요하지 않습니다.)

 

다만, 객체참조로 형식으로도 접근이 가능하나, 클래스 변수인지, 인스턴스 변수인지 헷갈리기 때문에 항상 클래스 변수로 접근하는 것이 올바른 사용법입니다.

두번째 줄처럼 static 변수를 객체 참조로 접근하는 것을 지양하라는 의미입니다!

 

static 메소드 안에 일반 메소드가 실행 가능할까?

 

가능합니다. 단, 정의된 방식처럼 파라미터로 객체의 인스턴스를 사용해야만 가능합니다.

만약 그렇지 않으면 Non-static method는 static 컨텍스트에서 사용할 수 없다는 에러 메세지를 받게 됩니다.

대부분 일반적인 상황으로는 안되는게 맞습니다.

 

이유 : static 메소드는 클래스 레벨에서 호출고 특정 인스턴스에 속하지 않기 때문에, 인스턴스 멤버에 접근할 수 없습니다.

정적 중첩 클래스에 대한 이해

public class OuterClass {

    // Static Nested Class
    static class NestedClass {
        static void innerStaticMethod() {
            System.out.println("This is a static method in a static nested class.");
        }
    }

    public static void outerMethod() {
        // You can call the static method of the nested class directly
        NestedClass.innerStaticMethod();
    }

 

우선 정의부터 명확해야합니다.

 

static 이라고 선언하는 중첩 클래스를 static nested class(정적 중첩 클래스)라고 합니다.

그리고 static이라고 선언되지 않으면, 이를 내부 클래스라고 합니다.

 

이 둘의 차이는 내부 클래스의 경우 내부의 구성원에 대한 모든 접근권한이 있지만, 정적 중첩 클래스는 외부 클래스의 정적 구성원에 대한 접근 권한만 갖고 있는 것입니다. 

 

 

중첩 클래스 예시입니다. main()메소드에서 new School.Student()를 실행하게 되면 Student 객체가 초기화되기 시작합니다.

1. School클래스의 static변수로, School클래스의 인스턴스 생성 없이 접근 가능합니다.

2. StudentName, StudentNickname 모두 Stduent의 클래스 변수이기 때문에 인스턴스 생성 없이 접근 가능합니다.

3. School의 인스턴스 변수로 직접 접근할 수 없어 객체를 생성하나 후 해당 값을 참조해 출력합니다. 다만 객체 생성 이후에 나오는 동작이기 때문에 출력이 가장 마지막에 됩니다.

 

이런 키워드를 인지하고 접근 권한이나 범위, 그리고 가독성등을 고려하여 inner 클래스 혹은 정적 중첩 클래스를 고민해보는 것이 좋은 방법일 것 같습니다.

 

최종 정리

1. static 변수는 클래스 레벨에서만 선언이 가능하다.

2. 객체 초기화 없이 정적 필드에 접근이 가능하다.

3. 각 클래스 별로 같은 이름의 static 변수 선언이 가능하다.

4. static 메소드를 재정의할 수 없습니다.

5. 추상 메서드는 static일 수 없습니다.
6. static 메서드는 this 키워드나 super 키워드를 사용할 수 없습니다.

7. 인스턴스 메서드는 인스턴스 메서드와 인스턴스 변수 모두에 직접 액세스할 수 있습니다

8. 인스턴스 메서드는 static 변수 및 static 메서드에 직접 액세스할 수도 있습니다
9. static 메소드는 모든 static 변수 및 기타 static 메소드에 액세스할 수 있습니다
10. static 메서드는 인스턴스 변수 및 인스턴스 메서드에 직접 액세스할 수 없습니다. 그렇게 하려면 객체 참조가 필요합니다.

11. static이 붙은 메서드(함수)에서는 인스턴스 변수를 사용할 수 없다

12. static메소드 안에 static메소드를 선언하는건 컴파일 에러가 발생한다. 단 중첩클래스를 활용해 유사하게 문제 해결이 가능하다.

추가

baeldung에서는 static 변수가 힙에 저장된다고 하는데, 찾아보니 자바 8 이전의 heap 메모리의 PermGen에 저장되는 것이었습니다! 해당 영역은 GC의 대상이 아닙니당. 그리고 8버전 이후에는 permGen에서 metaspace라고 명칭이 변경되고 메서드 영역에 저장된다는 것이 맞는 표현이니 알고 계시길 바랍니다~ㅎㅎ

 

StringUtils. CollectionUtils는 모두 static메소드로 이루어져 있다. 즉, 어디서든 사용 가능하다는 의미~!

 

 

https://www.baeldung.com/java-static