언어(Language)/Java

[Java] 자바 필드(Field) 개념 정리 및 예제

잇트루 2022. 9. 13. 06:10
반응형

필드 (Field)

필드는 클래스에 포함된 변수를 의미한다. 즉, 객체의 속성을 정의하는 공간이다.

 

자바에서 변수는 크게 클래스 변수(cv: class variable), 인스턴스 변수(iv, instance variable), 지역 변수(lv, local variable)가 있다. 필드에서 다루는 변수는 클래스 변수(cv)와 인스턴스 변수(iv)이다. 이 둘은 static 키워드를 통해 구분할 수 있다.

 

자바의 변수 종류

클래스 변수 : 필드 내에서 static 키워드와 함께 선언된 변수, static 변수 또는 공유 변수라고도 함

인스턴스 변수 : 필드 내에서 선언된 변수 (static 키워드 없음)

지역 변수 : 메서드 내에 포함된 모든 변수

class Variable {
    static int classVariable; // 클래스 변수(static 변수 또는 공유변수)
    int instanceVariable;     // 인스턴스 변수

    void variableMethod() {
        int localVariable;      // 지역변수, 메서드 내에서만 사용 가능
    }
}

세 가지 유형의 변수들은 서로 다른 유효 범위(scope)를 가진다.

 

각 변수들의 특징

인스턴스 변수(iv)

인스턴스(클래스를 통해 생성된 객체)가 가지는 속성을 저장하기 위한 변수이다. 따라서 new 생성자()를 통해 인스턴스가 생성될 때 만들어진다. 따라서 인스턴스를 생성한 뒤, ‘인스턴스명.인스턴스변수명’을 통해 사용할 수 있다.

 

인스턴스는 힙 메모리의 독립적인 공간에 저장되고, 동일한 클래스로부터 생성되었지만 객체의 고유한 개별성을 가진다.

class Variable {
    int instanceVariable = 10; // 클래스 변수 초기화

    public static void main(String[] args) {
        Variable instance = new Variable();
        System.out.println(instance.instanceVariable); // 10 출력
}

 

클래스 변수(cv)

클래스 변수는 인스턴스 변수와는 다르게 공통된 저장공간을 공유한다. 즉, 한 클래스로부터 생성되는 모든 인스턴스들이 특정한 값을 공유해야 하는 경우에 static 키워드를 사용하여 선언하게 된다.

클래스 변수는 인스턴스를 생성하지 않고도 ‘클래스명.클래스변수명’을 통해 사용이 가능하다.

class Variable {
    static int classVariable = 10; // 클래스 변수 초기화

    public static void main(String[] args) {
        System.out.println(Variable.classVariable); // 10 출력
}

 

지역 변수(lv)

지역 변수는 멤버 변수(클래스 변수, 인스턴스 변수)와는 구분된다. 지역 변수는 메서드 내에 선언되며 메서드 안에서만 사용이 가능하다.

또한, 멤버 변수와는 다르게 지역 변수는 스택 메모리에 저장되어 메서드가 종료되는 동시에 소멸된다.

class Variable {
    public static void main(String[] args) {
        int localVariable = 10;
        System.out.println(localVariable); // 10 출력
}

지역 변수는 값을 출력할 때, 초기화한 상태가 아니면 오류가 발생한다. 하지만, 멤버 변수(클래스 변수, 인스턴스 변수)는 직접적으로 초기화하지 않더라도 값 출력이 가능하다. 이때, 강제로 초기화한다. 따라서 지역 변수는 사용자에 의해 초기화하지 않으면 에러를 발생하므로 반드시 직접 초기화를 해야 한다.

 

static

자바 프로그래밍에서는 모든 객체와 메모리를 공유할 때 static 키워드를 사용한다.

static은 클래스 변수와 인스턴스 변수를 구분하기 위해 사용하며 static 키워드가 붙은 변수는 클래스 변수이다. 즉, static은 클래스의 구성요소인 필드, 메서드, 이너 클래스에서 사용하기 위한 변수이다.

 

이를 클래스 멤버(필드, 메서드, 이너 클래스)에서 사용한다고 하여 정적 멤버라 부른다. 클래스 변수는 접근 제한자에 따라 다른 클래스에서도 바로 사용이 가능하다.

class Variable {
    public static void main(String[] args) {
        // 다른 클래스
        System.out.println(StaticMember.num);
        System.out.println(StaticMember.str);
        System.out.println(StaticMember.pi);
}
    class StaticMember {
    static int num = 10;
    static String str = "안녕하세요";
    static double pi = 3.14;
}

 

정적 필드는 객체 간의 공유 변수 성질이 있다. 이는 메서드에서도 동일하게 적용된다. 일반적으로 메서드 앞에 static 키워드를 사용하면 이는 정적 메서드이다.

즉, 정적 메서드에서 여러 인스턴스들을 통해 클래스 변수를 사용하면 서로 공유한다.

public class StaticInstanceTest {
    public static void main(String[] args) {
        StaticInstance object1 = new StaticInstance();
        StaticInstance object2 = new StaticInstance();

        // 객체의 인스턴스 변수 접근
        object1.number1 = 10;
        object2.number1 = 50;
        System.out.println(object1.number1); // 10 출력
        System.out.println(object2.number1); // 50 출력

        // 객체의 클래스 변수 접근
        object1.number2 = 10;
        object2.number2 = 50;
        System.out.println(object1.number2); // 50 출력
        System.out.println(object2.number2); // 50 출력
    }
}

class StaticInstance {
	int number1 = 0;
	int static number2 = 0;
}

 

클래스 메서드(정적 메서드)의 경우 인스턴스 변수 또는 인스턴스 메서드를 사용할 수 없다.

또한, 클래스 메서드(정적 메서드)는 인스턴스 생성 없이 호출이 가능하다.

반대로, 인스턴스 메서드에서는 인스턴스 변수를 사용할 수 있다.

public class CarTest2 {
    public static void main(String[] args) {
    System.out.println(Car.str1); // 클래스 변수 바로 사용 가능
    // System.out.println(Car.str2); // 인스턴스 변수 바로 사용 불가능

    Car.ClassMethod(); // 클래스 메서드 바로 사용 가능
    // Car.InstanceMethod(); // 인스턴스 메서드 바로 사용 불가능

        // 객체는 클래스 변수와 클래스 메서드를 공유한다.
        Car car1 = new Car();
        Car car2 = new Car();

        // 클래스 변수는 모든 메모리를 공유한다.
        // 따라서 객체를 통해 수정해도 다른 객체나 직접 접근해도 수정된 결과를 출력한다.
        car.str1 = "클래스 변수입니다."; // 객체를 통해 클래스 변수 변경
        System.out.println(car1.str1); // 클래스 변수입니다. 출력
        System.out.println(car2.str1); // 클래스 변수입니다. 출력
        System.out.println(car.str1);  // 클래스 변수입니다. 출력

        // 반면, 인스턴스 변수는 독립적인 메모리를 가지고 있다.
        // 변경한 인스턴스만 수정된 상태로 출력
        car1.str1 = "인스턴스 변수입니다.";
        System.out.println(car1.str2); // 인스턴스 변수입니다. 출력
        System.out.println(car2.str2); // 인스턴스 변수 출력

    }
}

class Car {
    public static String str1 = "클래스 변수";
    public String str2 = "인스턴스 변수";

    public static void ClassMethod() { // 정적 메서드(클래스 메서드)
    System.out.println(str1); // 클래스 변수 사용 가능
    // System.out.println(str2); 인스턴스 변수 사용 불가능
    }

    public void InstanceMethod() { // 인스턴스 메서드
    System.out.println(str1); // 클래스 변수 사용 가능
    System.out.println(str2); // 인스턴스 변수 사용 가능
    }
}
반응형