[Java] Java 기초 - static 심화

Hyunjun Kim·2025년 3월 31일
0

Data_Engineering

목록 보기
19/153

1.

모모코딩 [자바] 변수 앞에 static 있을 때와 없을 때의 차이

Persion class에는
name과 population이라는 객체변수가 있다.
생성자에 의해 파라미터로 들어온 name은 객체변수에 세팅하고
총 인구수는 new 할 때 마다 하나씩 증가했으면 좋겠다 하고 population++; 를 했다. 생각대로 잘 되는지 Momo class main에서 객체를 만들어 보자.

class Person{
    String name;
    int population;

    Person(String name){
        this.name = name;
        population ++;
    }
}

public class Momo {
    public static void main(String[] args) {
        Person p1 = new Person("A");
        System.out.println(p1.population); // 출력결과 1

        Person p2 = new Person("B");
        System.out.println(p2.population); // 출력결과 1

        Person p3 = new Person("C");
        System.out.println(p3.population ); // 출력결과 1
    }
}

print의 결과가 셋 다 1이 나왔다. 위에 코드처럼 객체를 만들었을 때, 저장공간에 객체가 어떤 모습으로 만들어지는지에 확인해보자.

1,2,3을 기대했지만 생각대로 되지 않는다.

우리가 population을 static이 없는 객체변수로 생성했을 때 객체마다 population이 안에 새로 생기기 때문에 1,1,1로 출력이 된다.

그러면 1,2,3 으로 객체를 만들 때마다 population이 늘어나도록 하려면 어떻게 해야 하느냐?! population 앞에 static이라는 예약어를 붙여주어야 한다.

static이 붙은 애들은 클래스가 사용되는 시점에 사용되는 코드가 나오면 자기가 저장공간에 가서 자리를 잡는다.

그 다음에 Person객체를 생성하는 코드를 실행하면 저장공간에는 Person의 이름만 가진 객체가 만들어 지고

그 다음에 population +1 이 되어서 1로 변한다.

두번째 부터는 다른데 Person 객체가 생성되면서 name에 B가 세팅되고

population +1 이 되면서 숫자가 2로 변한다.

그 이후 p3 를 생성하게 되면 객체가 생성되면서 name 세팅,
population +1 이 되면서 숫자가 3으로 변한다.

이 static이라고 붙은 변수들은 클래스당 하나만 생겨서 더이상 만들어지지 않는다.

p3.population = 5;
System.out.println(p1.population); // 출력결과 5

이렇게 p3 객체로 접근해서 static 값을 바꾼 후에 population 값을 확인해 보면 5가 출력되는 것을 볼 수 있고, 다른 객체(p1)로 접근해서 확인을 해도 5가 나오는 것을 알 수 있다.

population을 static으로 바꾼 후 p1.population 에서 노란색 경고가 뜬다.

그 이유는 어차피 클래스 당 하나인 클래스 변수니까 static이 붙은 친구들은
class이름.변수이름 으로 사용해라 라는 것!

이렇게 클래스 이름. 으로 바꿔주니 경고 알림이 꺼졌다.





# 2. 참고 링크 : [생활코딩 JAVA 객체지향 프로그래밍 - 6. static](https://youtu.be/hvTuZshZvIo?si=yog6fEu8F98_JYlE)

Foo 클래스에서
public static String classVarpublic String instanceVar 를 만들어서 테스트를 해보자.

test1
class 를 통해서 classVar에는 접근이 되나?
또, class 를 통해서 instanceVar에는 접근이 되나? 를 따져보자.

클래스를 통해서는 당연히 클래스 변수에 접근이 된다.
클래스를 통한 인스턴스변수 접근은 에러.
인스턴스는 인스턴스를 통해서 사용하도록 고안된 변수다. 라는 것.

test2

class Foo 안에
public static void classMethod 를 생성해서
classVar에 접근을 시도했을 때는 어떻고
instanceVar에 접근을 시도했을 때는 어떤지를 확인해보자.

classMethod 안에서는 클래스 변수에는 접근이 되는데
인스턴스 변수에는 접근할 수 없다. 에러. 라는 것을 알 수 있다.

test3
인스턴스 변수를 만들어보자

class Foo 안에
public void instanceMethod 를 생성해서
아까 처럼 classVar 와 instanceVar에 접근을 해서 확인해보자.

인스턴스 메소드 안에서는
클래스변수와 인스턴스 변수 모두 접근 가능하다.

test4
이번에는 main에서
Foo의 classMethod와 instanceMethod 를 호출해보자.

Foo의 클래스메소드는 잘 호출된다. 왜냐면 클래스 소속이니까.
하지만
Foo의 인스턴스 메소드는 접근이 안된다.
인스턴스 메소드는 인스턴스 소속이기 때문에 클래스를 통해서 접근하는 것은 금지되어 있다.

정리 :
클래스를 통해서 직접 인스턴스 변수/인스턴스 메소드에 접근하는 것은 금지되어 있다!



Foo f1 = new Foo(); 로 인스턴스를 생성했을 때
내부적으로 어떤 일이 생기는지 알아보자.

  1. f1이라는 인스턴스가 만들어지고
  2. 그 인스턴스는 클래스를 원형으로 하기 때문에 클래스에 있는 여러가지 멤버들을 복제해오는데

첫번째. classVar는 static이다. 누구 소속일까? class의 소속이다.
그래서 f1에는 실제 값이 존재하지 않고, Foo라고 하는 class를 가리키고 있다.

그리고 instanceVar는 Foo에서 f1이라는 인스턴스가 생성될 때, instanceVar라는 변수가 생성되면서, class에 값도 세팅되어있다면 그 값까지 복제가 된다.
그리고 class의 instanceVar, f1의 instanceVar는 서로 링크걸려있지 않기 때문에 f1의 instanceVar을 바꾼다고 해서 class의 instanceVar가 바뀌지 않는다.

하지만 f1의 classVar를 바꾼다고 하면 class의 classVar는 바뀐다.
(반대로 class의 classVar가 바뀌어도 f1의 classVar도 바뀜)

메소드도 마찬가지로 f1의 static classMethod는 class를 참조하는 것이다.
instanceMethod는 클래스에 있는 인스턴스 메소드를 복제한 것이고 서로 독립된 존재이다.

중요한 거 : class의 변수를 바꾸면 모든 instance의 변수의 값이 바뀐다.
또 인스턴스에서 클래스 변수의 값을 바꿀 수 있는데 그렇게 되면 클래스의 변수가 바뀌고 걔를 사용하고 있는 모든 인스턴스의 값도 바뀐다.



test5
f1은 classVar, instanceVar에 접근하면 어떻게 될까?

f1의 classVar 접근은 class 의 static classVar를 가리키니까
I class var 가 출력된다.
f1의 instanceVar는 class에 기본적으로 세팅되어있던 값이 복제된 상태이기 때문에 I instance var 라는 값이 출력된다.

test6
f1의 classVar를 변경한다면 어떻게 될까?

f1은 인스턴스인데 인스턴스의 classVar는 static이기 때문에 Foo class에 있는 classVar라고 하는 변수의 값이 "changed by f1" 로 바뀌게 된다.

그 상태에서 Foo.classVar 를 출력하면 "changed by f1"이 나온다.
f2.classVar 는 어떻게 될까? f2는 인스턴스인데 f2의 classVar는 class Foo의 cassVar를 가리키니까 결과는 동일한 "changed by f1" 이 나오게 된다.

test6
f1의 instanceVar 를 바꾼 후
f1.instanceVar, f2.instanceVar 는?

f1은 자신의 instanceVar를 바꿨으니 이상태에서 f1의 인스턴스 변수에 접근하면 바뀐 결과 "changed by f1"를 보지만
f2의 인스턴스에 접근하게 되면 f2는 f1과 독립적인 변수를 운영하고 있기 때문에 값이 바뀌지 않게 된다.





3. class 앞에 static 붙는 이유

자바에서 class 앞에 static을 붙일 수 있는 경우는 "내부 클래스(중첩 클래스, Nested Class)"일 때 이다. 즉, 클래스 내부에 선언된 클래스에만 static을 붙일 수 있다.

1) static class란?

✔ "외부 클래스의 인스턴스 없이도 사용 가능한 내부 클래스"

일반적으로 내부 클래스(Inner Class)는 외부 클래스의 객체를 만들어야 사용 가능하다. 하지만 static을 붙이면 외부 클래스의 인스턴스와 상관없이 사용 가능해짐.

class Outer {
    static class Inner {
        void show() {
            System.out.println("Static 내부 클래스 실행!");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Outer.Inner obj = new Outer.Inner(); // 외부 클래스 객체 없이 직접 사용!
        obj.show();
    }
}
  • ✔ Outer 클래스의 객체 없이 Outer.Inner를 바로 사용할 수 있음!

2) static이 없는 내부 클래스는?

만약 static을 안 붙이면 외부 클래스의 객체가 먼저 필요하다.

class Outer {
    class Inner {
        void show() {
            System.out.println("일반 내부 클래스 실행!");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        Outer outer = new Outer(); // 먼저 외부 클래스 객체를 생성해야 함
        Outer.Inner obj = outer.new Inner();
        obj.show();
    }
}
  • ✔ 외부 클래스의 객체 없이 사용할 수 없다는 차이점이 있음!

예전에 자바를 할 때 알고 있던 내용이지만
너무 오랜만에 돌아왔는지 static 개념이 어렵게 느껴져서 정리했다.
너무 줄글이라서 다시 보게될지는 모르겠지만
까먹었을 때 돌아와서 보면 금방 다시 기억나겠지..

profile
Data Analytics Engineer 가 되

0개의 댓글