변수는 클래스변수
, 인스턴스변수
, 지역변수
세 종류 있다. 변수의 종류는 변수가 어느 영역에 선언되었는지를 확인하는 것이 중요하다.
멤버변수를 제외한 나머지 변수들은 모두 지역변수
이며, 멤버변수 중 static이 붙은 것은 클래스변수
, 붙지 않은 것은 인스턴스변수
이다.
class Variables {
int iv; //인스턴스 변수
static int ic; //클래스 변수
void method() {
int lv = 0; //지역 변수
}
}
클래스 영역에 선언되며, 인스턴스를 생성할 때 만들어진다. 그렇기 때문에 인스턴스 변수의 값을 읽어 오거나 저장하기 위해서는 먼저 인스턴스를 생성해야 한다. 인스턴스는 독립적인 저장공간을 가지므로 서로 다른 값을 가질 수 있다. 인스턴스마다 고유한 상태를 유지해야하는 속성의 경우, 인스턴스 변수로 선언한다.
클래스 변수는 인스턴스 변수 앞에 static을 붙이기만 하면 된다. 클래스변수는 모든 인스턴스가 공통된 저장공간 (변수)를 공유하게 된다. 한 클래스의 모든 인스턴스들이 공통적인 값을 유지해야하는 속성의 경우, 클래스 변수로 선언해야 한다.
클래스변수는 인스턴스를 생성하지 않고도 언제라도 바로 사용할 수 있다는 특징이 있으며, 클래스이름.클래스변수
와 같은 형식으로 사용한다.
클래스가 메모리에 로딩될 때 생성되어 프로그램이 종료될 때까지 유지되며, public을 앞에 붙이면 같은 프로그램 어디서나 접근할 수 있는 전역변수 (global variable)의 성격을 갖는다.
메서드 내에 선언되어 메서드 내에서만 사용 가능하며, 메서드가 종료되면 소멸되어 사용할 수 없게 된다. for문 또는 while문의 블럭 내에 선언된 지역변수는 지역변수가 선언된 블럭 {} 내에서만 사용 가능하며, 블럭을 벗어나면 소멸되어 사용할 수 없게 된다.
💡 static 변수 = 정적변수 = 클래스 변수 = 공용 변수
한 번 메모리에 올려 모든 인스턴스가 공유하는 변수이다.
프로그램이 실행되며 클래스와 클래스 멤버들이 method area
에 올라간다.
인스턴스가 생성되면서 Heap 영역에 인스턴스가 올라가고 참조변수에 주소값이 대입된다. 인스턴스 변수들도 인스턴스 내에 저장된다.
(static 변수가 한 번도 쓰이지 않았을 때) 객체가 생성되기 전에 static이 있으면 먼저 메모리를 할당하고 값을 가져온다.
(static 변수가 메모리에 올라와 있다면) 올라온 static 변수를 공유한다.
class InstCnt {
static int instNum;
InstCnt() {
instNum++;
System.out.println("인스턴스 생성 : " + instNum);
}
}
public class StaticTest {
public static void main(String[] args) {
InstCnt i1 = new InstCnt();
InstCnt i2 = new InstCnt();
InstCnt i3 = new InstCnt();
}
}
//result
인스턴스 생성 : 1
인스턴스 생성 : 2
인스턴스 생성 : 3
class card {
String kind; //카드 무늬 - 인스턴스 변수
int number; //카드 숫자 - 인스턴스 변수
static int width = 100; //카드 폭
static int height = 250; //카드 높이
}
- 값의 참조가 목적인 변수
- 값의 공유가 목적인 변수
class Circle {
static final double PI = 3.14;
private double radius;
...
}
instance method | static method (class method) |
---|---|
인스턴스 생성 후, 참조변수.메서드명() 으로 호출 | 객체 생성 없이 클래스이름.메서드명() 으로 호출 |
*인스턴스 멤버와 관련된 작업을 하는 메서드 | 인스턴스 멤버와 무관한 작업을 하는 메서드 |
메서드 내에서 인스턴스 변수 사용이 가능함 | 메서드 내에서 인스턴스 변수 사용이 불가 |
인스턴스와 관계없는 (인스턴스 변수나 인스턴스 메서드를 사용하지 않는) 메서드를 클래스 메서드 (static method)로 정의한다.
인스턴스 변수를 사용하지 않는다고 해서 반드시 클래스 메서드로 정의해야하는 것은 아니지만 특별한 이유가 없는 한 그렇게 하는 것이 일반적이다.
System.out.println
java.lang.System.out.println(...);
System
은 java.lang 패키지에 묶여 있는 클래스의 이름import java.lang.*;
out
은 클래스 System의 이름을 통해 접근하므로, 이는 System 클래스의 클래스 변수 이름임을 유추할 수 있다.println
은 out이 참조하는 인스턴스의 메소드이다.main()
public static void main(String[] args) {}
main
메서드가 static
인 이유?main
메서드가 public
인 이유?⭐️ 생성자는 static vs non-static?
It's static in the sense that you can invoke it without a callee, but it's non-static in the sense that you have a
this
reference.
참고 : https://stackoverflow.com/questions/29145700/can-we-say-constructors-are-methods-in-java
💡 클래스 변수와 클래스 메서드
- 클래스의 멤버변수 중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있으면,
static
을 붙여준다.- 작성한 메서드 중에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에
static
을 붙일 것을 고려한다.