본문 바로가기
Java/객체지향 프로그래밍 기초

3. 필드(Field)

by mozzi329 2022. 7. 8.
728x90
 

 

     

    📌 Goal

    • 객체의 속성을 정의하는 필드를 이해하고, 세 가지 종류의 변수를 구분할 수 있다.
    • 각각의 변수가 저장되는 위치를 설명하고, 그 차이를 설명할 수 있다.
    • static 키워드가 무엇이며, 언제 사용되는 지 설명할 수 있다.

     

    📌 필드(Field)

    ‘클래스에 포함된 변수'를 의미하는 것으로 객체의 속성을 정의할 때 사용

    자바에서 변수는 크게 클래스 변수(class variable),인스턴스 변수(instance variable),지역 변수(local variable)로 구분된다. 이 세 가지 유형의 변수들은 주로선언된 위치에 따라 그 종류가 결정되며 각각 다른 유효 범위(scope)를 가지게 된다. 

     

    아래 예시를 한번 살펴보자.

    class Example { // => 클래스 영역
    	int instanceVariable; // 인스턴스 변수
    	static int classVariable; // 클래스 변수(static 변수, 공유변수)
    
    	void method() { // => 메서드 영역
    		int localVariable = 0; // 지역 변수. {}블록 안에서만 유효
    	}
    }
    

     

    ✔️ 인스턴스 변수(Instance Variable)

    인스턴스 변수(Instance Variable)는 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수다.

    new 생성자() 를 통해 인스턴스가 생성될 때 만들어진다. 클래스를 통해 만들어진 인스턴스는 힙 메모리의 독립적인 공간에 저장되고, 동일한 클래스로부터 생성되었지만 객체의 고유한 개별성을 가진다.

     

    ✔️ 클래스 변수(Class Variable)

    클래스 변수(Class Variable)는 독립적인 저장 공간을 가지는 인스턴스 변수와 다르게 공통된 저장공간을 공유한다.

    따라서 한 클래스로부터 생성되는 모든 인스턴스들이 특정한 값을 공유해야하는 경우에 주로 static 키워드를 사용하여 클래스 변수를 선언한다. 또한, 클래스 변수는 인스턴스 변수와 달리 인스턴스를 따로 생성하지 않고도 언제라도 클래스 명. 클래스 변수 명을 통해 사용이 가능하다. 위의 코드 예제로 예를 들면,Example.classVariable로 클래스 변수를 사용할 수 있다.

     

    ✔️ 지역 변수(Local Variable)

    지역변수(Local Variable)는 메서드 내에 선언되며 메서드 내({} 블록)에서만 사용가능한 변수이다.
    멤버 변수와는 다르게 지역변수는 스택 메모리에 저장되어 메서드가 종료되는 것과 동시에 함께 소멸되어 종료 시 더이상 사용할 수 없다. 또한 힙 메모리에 저장되는 필드 변수는 객체가 없어지지 않는 한 절대로 삭제되는 않는 반면, 스택 메모리에 저장되는 지역변수는 한동안 사용되지 않는 경우 가상 머신에 의해 자동으로 삭제된다.

    메모리 영역

    마지막으로 직접 초기화하지 않으면 값을 출력할 때에 오류가 발생하는 지역변수와는 다르게 필드 변수는 직접적으로 초기화를 실행하지 않더라도 강제로 초기화가 이뤄진다. 이것 또한 메모리의 저장 위치와 긴밀한 연관성을 가집니다. 힙 메모리에는 빈 공간이 저장될 수 없기 때문에 이곳에 저장되는 필드는 강제로 초기화되지만, 스택 메모리는 강제로 초기화되지 않으므로 지역 변수는 선언 시 반드시 초기화를 실행해주어야 한다.

     

    📌 static 키워드

    클래스 변수와 인스턴스 변수를 구분하기 위해 static키워드의 유무를 확인

    ※ 모든 객체와 메모리를 공유한다.

     

    static은 클래스의 멤버(필드, 메서드, 이너 클래스)에 사용하는 키워드이다. static키워드가 붙어있는 멤버를 우리는 정적 멤버(static member)라고 부르고 static이 붙어있지 않은 인스턴스 변수와 구분한다.

     

    ✔️ 인스턴스 멤버 vs 클래스 멤버

    둘을 구분하는 가장 큰 차이는 인스턴스 멤버는 반드시 객체를 생성한 이후에 변수와 메서드에 접근해야 해당 멤버를 사용가능한 반면, static키워드로 정의되어 있는 클래스 멤버들은 인스턴스의 생성 없이도 클래스명.멤버명 만으로도 사용이 가능하다.

     

    ✔️ 클래스명.멤버명

    static키워드를 사용하는 정적 멤버를 클래스명.멤버명으로 사용할 수 있는 것 또한 메모리의 저장 위치와 관련이 있다. static키워드로 선언된 정적 멤버는 클래스 내부에 저장 공간을 가지고 있기 때문에 객체 생성 없이 곧바로 사용할 수 있다.

     

    public class StaticTest {
        public static void main(String[] args) {
            StaticExample staticExample = new StaticExample();
            System.out.println("인스턴스 변수: " + staticExample.num1); // static 키워드가 없는 인스턴스 변수
            System.out.println("클래스 변수: " + StaticExample.num2); //static 키워드가 있는 클래스 변수
        }
    }
    
    class StaticExample {
        int num1 = 10; // 객체 생성 시 공간 할당
        static int num2 = -10; // 클래스 자체에 num2의 공간 할당
    }
    
    //Output
    인스턴스 변수: 10
    클래스 변수: -10
    

     

    ❗️static 키워드를 사용하면 모든 인스턴스에 공통적으로 적용되는 값을 공유할 수 있다.

    public class StaticFieldTest {
        public static void main(String[] args) {
            StaticField staticField1 = new StaticField(); // 객체 생성
            StaticField staticField2 = new StaticField();
    
            staticField1.num1 = 100;
            staticField2.num1 = 1000;
    
            System.out.println(staticField1.num1);
            System.out.println(staticField2.num1);
    
            staticField1.num2 = 150;
    				// staticField1과 staticField2의 num2 주소는 공유된다.
            staticField2.num2 = 1500;
            System.out.println(staticField1.num2);
            System.out.println(staticField2.num2);
    
        }
    }
    
    class StaticField {
        int num1 = 10;
        static int num2 = 15;
    }
    
    //출력값
    100
    1000
    1500
    1500
    

     

    StaticField클래스에 인스턴스 필드(num1)와 정적 필드(num2)를 각각 선언하고, 대조를 위해 staticField1와 staticField2객체를 생성한다. num1의 경우에는 각각의 변수가 고유성을 가지기 때문에 100과 1000으로 따로 출력되는 반면에, num2의 경우는 앞서 배웠던 것처럼 값 공유가 일어나 1500이 출력값으로 두 번 반복되고 있다.

     

    ❗️기억해야할 것

    정적 필드(static)는 객체 간 공유 변수의 성질이 있다

    메서드에서도 일반적인 메서드 앞에 static키워드를 사용하면 해당 메서드는 정적 메서드가 된다. 정적 메서드도 정적 필드와 마찬가지로 클래스명만으로 바로 접근이 가능하다.

     

    정적 메서드(static)의 경우 인스턴스 변수(non-static) 또는 인스턴스 메서드(non-static)를 사용할 수 없다

    정적 메서드는 인스턴스 생성 없이 호출이 가능하기 때문에 정적 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수 있기 때문이다.

     

    댓글