자바를 공부하다보면 자주 보이는 것이 있다. 바로 static이다.
public class Practice {
public static void main(String[] args) {
System.out.println("a");
}
}
거두절미하고, static이란
static - class method
no static - instance method
이다. 즉, 메소드를 정의할 때 static이라는 키워드를 쓰면 그 메소드는 클래스 소속이고, static이라는 키워드를 쓰지 않으면 그 메소드는 인스턴스의 소속이라는 것이다.
static 메소드는 클래스의 메소드로, 프로그램에서 한 번만 정의된다. 여러 개 가질 수 없는 유일무이한 메소드이다.
반면 static이 아닌 메소드는 인스턴스의 메소드로, 프로그램 안에서 여러 개 있을 수 있고, 그 인스턴스를 통해서 접근하는 메소드이다.
static 변수와 메소드는 클래스에서 생성된 모든 인스턴스가 공유하는 자원이다. 그리고 인스턴스를 만들지 않고도 클래스에서 직접 호출할 수 있다.
class Foo{
public static String classVar = "I am class variation";
public String instanceVar = "I am instance variation";
public static void classMethod() {
System.out.println(classVar); // Ok
// System.out.println(instanceVar); // Error
}
public void instanceMethod() {
System.out.println(classVar); // Ok
System.out.println(instanceVar); // Ok
}
}
public class StaticApp {
public static void main(String[] args) {
System.out.println(Foo.classVar); // OK
// System.out.println(Foo.instanceVar); // Error
Foo.classMethod();
// Foo.instanceMethod();
Foo f1 = new Foo();
Foo f2 = new Foo();
//
System.out.println(f1.classVar); // I am class variation
System.out.println(f1.instanceVar); // I am instance variation
//
f1.classVar = "changed by f1";
System.out.println(Foo.classVar); // changed by f1
System.out.println(f2.classVar); // changed by f1
//
f1.instanceVar = "changed by f1";
System.out.println(f1.instanceVar); // changed by f1
System.out.println(f2.instanceVar); // I am instance variation
}
}
가령 위 코드를 봤을 때, 인스턴스를 생성하지 않고 클래스에서 바로 인스턴스의 변수와 메소드에 접근할 수 없다. 즉, static이 아닌 변수와 메소드는 f1, f2 인스턴스를 생성해야 비로소 접근할 수 있게 된다.
static 변수와 메소드는 해당 클래스로 생성된 모든 인스턴스가 공유하는 자원이기 때문에 인스턴스 모두는 같은 static 변수와 메소드를 사용할 수 있다.
f1.classVar = "changed by f1";
이 코드를 통해 f1 인스턴스에 있는 classVar의 값을 변경했을 때, 이것은 static 변수이기 때문에 f2 인스턴스 및 Foo 클래스의 classVar도 같은 값으로 적용된 것을 볼 수 있다.
반면 static이 아닌 변수와 메소드는 인스턴스마다 고유의 값을 가지기 때문에 인스턴스에서 변경한다고 해도 다른 인스턴스에 어떠한 영향도 끼치지 않는다.
f1.instanceVar = "changed by f1";
이 코드에서 f1 인스턴스에 있는 instanceVar의 값을 변경했을 때, 이것은 static이 아닌 변수이기 때문에 f2 인스턴스의 instanceVar 값에 아무런 영향을 미치지 못한 것을 알 수 있다.
위 그림을 보면, f1 인스턴스의 classVar은 static으로 class 소속이다. 실제 값이 존재하지 않고 Foo라는 클래스를 가리키고 있을 뿐이다. 그런데 instanceVar은 Foo에서 f1이라는 인스턴스가 생성될 때 instanceVar라는 변수가 생성되면서, 만약에 클래스에 값까지 세팅되어 있다면 그 값까지 복제되는 것이다. 그리고 클래스 Foo의 instanceVar와 인스턴스 f1의 instanceVar은 서로 링크 걸려있지 않기 때문에 f1의 값을 바꾼다고 해서 Foo의 값이 바뀌지 않는다. 인스턴스 f1의 classVar을 바꿨을 때 클래스 Foo의 classVar도 같이 바뀌는 것과는 대조적이다.
메소드도 마찬가지이다. 인스턴스 f1의 classMethod는 클래스 Foo의 classMethod를 참조하는 것으로 그 둘은 독립적이지 않고, 인스턴스 f1의 instanceMethod는 클래스 Foo의 instanceMethod를 복제한 것으로 그 둘은 독립이다.
인스턴스 f2를 추가로 생성했을 때, f2의 classVar, classMethod를 변경하면 클래스 Foo, 인스턴스 f1 모두 변경되고, f2의 instanceVar, instanceMethod를 변경했을 때에는 클래스 Foo, 인스턴스 f1 모두 영향을 받지 않는다.
'Language > Java' 카테고리의 다른 글
Overriding, Overloading (0) | 2022.11.14 |
---|---|
생성자(constructor)와 this (0) | 2022.11.13 |
접근 제어자 (access level modifiers) (0) | 2022.11.10 |
main 메소드 (0) | 2022.11.10 |
== vs equals (0) | 2022.11.09 |