static 키워드의 개념과 잘못 사용했을 때 발생할 수 있는 문제에 대해 설명해주세요.
static 키워드는 정적 또는 고정된이라는 의미이며, static이라는 키워드를 사용하여 static변수와 static메소드를 만들 수 있는데 다른 말로는 정적필드와 정적메소드라고 하며 이 둘을 합쳐 정적 멤버라고 한다.
정적 필드와 정적 메소드는 객체에 소속된 멤버가 아니라 클래스에 고정된 멤버이다. 그렇기에 클래스 로더가 클래스를 로딩해서 메모리 메소드 영역에 적재할때 클래스 별로 관리된다. 따라서 클래스의 로딩이 끝나는 즉시 바로 사용할 수 있다.

메소드 영역(Method Area): JVM이 시작할 때 생성되는 영역으로 JVM에 의해 사용된다. 이 영역에는 각 클래스와 인터페이스의 실행에 필요한
바이트 코드, 이름, 데이터 타입, 상수, static 변수, 공유 자원 등이 저장된다.힙 영역(Heap Area):
모든 객체와 배열이 이 영역에 할당된다. 힙 영역은 JVM의 시작과 동시에 할당되며, 자바 런타임에 동적으로 할당되고 해제된다. 즉,new 키워드를 통해 생성된 객체는 모두 힙 영역에 생성되며,가비지 컬렉터에 의해 이 영역의 불필요한 객체들이 정리된다.스택 영역(Stack Area): 스택 영역은 각
스레드가 호출하는 메소드에 대한 정보를 저장하는 영역이다. 메소드가 호출되면 스택 프레임이라는 블록이 스택 영역에 생성되며, 이 블록은 지역 변수, 매개 변수, 중간 연산 결과 등 메소드의 작업을 위한 데이터를 포함한다. 메소드가 작업을 완료하면 해당 스택 프레임은 스택에서 제거된다.
위의 그림과 같이 static 키워드로 생성된 정적멤버들은 Heap 영역이 아닌 static 영역 (Class 영역)에 할당된다. static 영역에 할당된 메모리는 모든 객체가 공유하여 하나의 멤버를 어디서든 참조할 수 있는 장점을 가지지만 가비지 컬렉터의 관리 영역 밖에 존재하기 때문에 static영역에서 있는 멤버들은 프로그램이 종료시까지 메모리에 할당된 채로 존재하게 된다. 그렇기에 static을 너무 남발하게 되면 만들고자하는 시스템에 악영향을 줄 수 있다.
static을 사용하면 객체 지향의 캡슐화, 상속, 다형성을 활용하기 어려워진다.static 메소드나 변수는 보통 전역상태를 나타내기 때문에 테스트시 원하는 상태로 쉽게 변경할 수 없기 때문이다.public class Main {
public static void main(String args[]) {
System.out.println(Static.staticStr);
//System.out.println(Static.str); //Non-static field 'str' cannot be referenced from a static context
Static.staticMethod();
Static staticInstance = new Static();
System.out.println(staticInstance.str);
staticInstance.method();
}
}
public class Static {
public static String staticStr = "Hello, I'm static string";
public String str = "Hello, I'm string";
public static void staticMethod() {
System.out.println("Hello I'm static method");
System.out.println(staticStr);
//System.out.println(str); //Non-static field 'str' cannot be referenced from a static context
}
public void method() {
System.out.println("Hello I'm method");
System.out.println(staticStr);
System.out.println(str);
}
}
위의 코드에서 staticMethod 살펴보면 static 변수 staticStr는 호출가능하지만 str 변수를 호출하지 못한다.
하지만 method에서는 staticStr와 str 둘 다 호출이 가능한 걸 확인할 수 있다.
그리고 Main메소드를 살펴보면 static 메소드나 변수는 클래스명.변수 또는 클래스명.메소드명로 바로 호출할 수 있지만 str, method는 new 연산자를 통한 객체 참조를 통해 호출할 수 있다.