static과 nonstatic
변수와 메서드
class Variables
{
int iv; //인스턴스 변수
static int cv; //클래스 변수
void method(){
int lv; //지역변수
}
}
변수 종류 |
선언위치 |
생성시기 |
클래스변수 |
클래스 영역 |
클래스가 메모리에 올라갈 때 |
인스턴스 변수 |
인스턴스가 생성되었을 때 |
|
지역변수 |
클래스 영역 이외의 지역 |
변수 선언문이 수행되었을 때 |
멤버 변수에는 클래스변수와 인스턴스 변수가 있으며 static이 붙으면 클래스 변수 없으면 인스턴스 변수로 구분된다.
인스턴스 변수
클래스 영역에 선언되며, 클래스의 인스턴스를 생성할 때 만들어진다. 그렇기 때문에 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야만 한다. 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스 변수로 선언
클래스 변수
선언하는 방법은 인스턴스 변수 앞에 static만 붙이면된다. 인스턴스마다 독립적인 저장공간을 갖는 인스턴스 변수와는 달리 클래스 변수는 모든 인스턴스가 공통된 저장공간을 공유하게 된다. 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 클래스 변수로 선언해야한다. 클래스 변수는 인스턴스변수와 달리 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다는 특징이 있으며, '클래스이름.클래스변수' 와 같은 형식으로 사용한다. ex) Variables.cv 와 같이 사용
클래스가 메모리에 로딩 될 때 생성되어 프로그램이 종료될 때 까지 유지되며, public을 앞에 붙이면 같은 프로그램 내에서 어디서나 접근할 수 있는 전역변수의 성격을 갖는다.
지역변수
메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 된다.
JVM의 메모리 구조
-Method 영역
-Heap 영역
-Call Stack 영역
메소드 영역
프로그램 실행 중 어떤 클래스가 사용되면 JVM은 해당 클래스의 클래스 파일(*.class)을 읽어서 분석하여 클래스에 대한 정보(클래스 데이터)를 이곳에 저장한다. 이 때 그 클래스의 클래스 변수도 이 영역에 함께 생성된다.
힙영역
인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다. 즉, 인스턴스 변수들이 생성되는 공간이다.
호출스택
호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다. 메서드가 호출되면, 호출 스택에 호출된 메서드를 위한 메모리가 할당되며, 이 메모리는 메서드가 작업을 수행하는 동안 지역변수들과 연산의 중간결과 등을 저장하는데 사용된다. 그리고 메서드가 작업을 마치면 할당되었던 메모리공간은 반환되어 비워진다.
각 메서드를 위한 메모리상의 작업공간은 서로 구별되며, 첫 번째로 호출된 메서드를 위한 작업공간이 호출스택의 맨 밑에 마련되고, 첫 번째 메서드 수행 중에 다른 메서드를 호출하면 첫 번째 메서드의 바로 위에 두 번째로 호출된 메서드를 위한 공간이 마련된다.
이 때 첫 번째 메서드는 수행을 멈추고, 두 번째 메서드가 수행되기 시작한다. 두 번째로 호출된 메서드가 수행을 마치게 되면, 두 번째 메서드를 위해 제공되었던 호출스택의 메모리공간이 반환되며, 첫 번째 메서드는 다시 수행을 계속 하게 된다. 첫 번째 메서드가 수행을 마치면, 역시 제공되었던 메모리 공간이 호출스택에서 제거되며 호출스택은 완전히 비워지게 된다. 호출스택의 제일 상위에 위치하는 메서드가 현재 실행중인 메서드이며, 나머지는 대기상태에 있게 된다. 만약 반환형이 있다면 호출했던 메서드에게 반환데이터를 넘겨주고 종료한다.
정리
-메서드가 호출되면 수행에 필요한 만큼의 메모리를 스택에 할당받는다.
-메서드가 수행을 마치고나면 사용했던 메모리를 반환하고 스택에서 제거된다.
-호출스택의 제일 위에 있는 메서드가 현재 실행중인 메서드다.
-아래에 있는 메서드가 바로 위의 메서드를 호출한 메서드이다.
-반환형이 있다면 호출했던(바로아래 있는 메서드) 메서드에게 반환 데이터를 넘겨주고 종료된다.
클래스 메서드(static메서드)와 인스턴스 메서드
클래스 메서드도 클래스 변수처럼, 객체를 생성하지 않고도 클래스이름.메서드이름 와 같은 식으로 호출이 가능하다. 반면에 인스턴스 메서드는 반드시 객체를 생성해야만 호출할 수 있다. 그렇다면 언제 클래스 메서드로 정의해야 할까?
인스턴스 메서드는 인스턴스 변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메서드이다.
인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드(static)로 정의한다.
정리
1.클래스를 설계할 때 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙인다.
-생성된 각 인스턴스는 서로 독립적이기 때문에 서로 다른 값을 유지한다. 그러나 모든 인스턴스에서 같은 값이 유지되어야 할 때 static을 붙여 클래스 변수로 정의해야한다.
2.클래스변수(static변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
-static이 붙은 변수는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문이다.
3.클래스 메서드(static메서드)는 인스턴스 변수를 사용할 수 없다.
-인스턴스 변수는 인스턴스가 반드시 존재해야만 하는데 클래스 메서드는 인스턴스 생성없이 호출 가능하므로 클래스 메서드가 호출 되었을 때 인스턴스가 존재하지 않을 수도 있다. 그래서 클래스 메서드에서 인스턴스변수의 사용을 금지한다. 반대로 인스턴스 변수나 메소드에서는 static이 붙은 멤버들을 사용하는 것이 언제나 가능하다.
4.메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
-메서드의 작업내용 중에서 인스턴스 변수를 필요로 한다면, static을 붙일 수 없다. 반대로 인스턴스변수를 필요로 하지 않는다면 static을 붙이자. 메서드 호출시간이 짧아지므로 성능이 향상된다. static을 안 붙인 메서드는 실행 시 호출되어야할 메서드를 찾는 과정이 필요하기 때문.