클래스 / 객체 / 정적(Static)
클래스?
정의 객체를 정의해 놓은 것, 객체를 정의하는 틀 또는 설계도
용도 객체를 생성하는 데 사용
객체?
정의 실제로 존재하는 것 (프로그래밍에서의 객체는 클래스에 정의된 내용대로 메모리에 생성된 것을 뜻함)
용도 객체가 가지고 있는 기능과 속성에 따라 다름
유형의 객체 책상, 의자, 자동차, TV와 같은 사물
무형의 객체 수학공식, 프로그램 에러와 같은 논리나 개념
ex) TV설계도(클래스)는 TV라는 제품(객체)을 정의한 것이며 TV(객체)를 만드는 데 사용된다.
클래스를 먼저 작성한 다음, 클래스로부터 객체를 생성하여 사용한다.
-> 식별 가능한 개체 또는 사물이다. 객체는 구별 가능한 식별자, 특징적인 행동, 변경 가능한 상태를 가진다. 인스턴스들을 통칭하는 용도로 사용한다.
객체의 속성과 기능
- 객체는 속성과 기능의 집합이다.
- 속성과 기능을 해당 객체의 멤버(구성원)이라고 한다.
속성 - 멤버 변수(variable)
기능 - 메서드(method)
ex) 채널 -> int channel
채널 높이기 -> channelUp() {...}
인스턴스?
클래스로부터 객체를 만드는 과정 = 클래스의 인스턴스화
어떤 클래스로부터 만들어진 객체 = 해당 클래스의 인스턴스
인스턴스는 객체와 같은 의미지만, 객체는 모든 인스턴스를 대표하는 포괄적인 의미를 갖고 있으며, 인스턴스는 어떤 클래스로부터 만들어진 것인지를 보다 강조하는 의미를 갖고 있다.
클래스 ---인스턴스화----> 인스턴스(객체)
정적(Static)?
- static은 클래스 멤버라고 하며, 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스별로 관리된다.
- static 키워드를 통해 생성된 정적멤버들은 PermGen 또는 Matespace에 저장되며 저장된 메모리는 모든 객체가 공유하며 하나의 멤버를 어디서든지 참조할 수 있는 장점이 있다.
- 다만, GC의 관리 영역 밖에 존재하기 때문에 프로그램 종료시까지 메모리가 할당된 채로 존재한다. 따라서 너무 많이 사용하면 시스템 성능에 악영향을 줄 수 있다.
static 메서드와 인스턴스 메서드
메서드 앞에 static이 붙어 있으면 => 클래스 메서드
붙어 있지 않으면 => 인스턴스 메서드
클래스 메서드도 객체를 생성하지 않고 '클래스이름.메서드이름(매개변수)' 형식으로 호출이 가능함
반면, 인스턴스 메서드는 반드시 객체를 생성해야만 호출할 수 있음
인스턴스 메서드
- 인스턴스 변수와 관련된 작업을 함.
- 메서드의 작업을 수행하는 데 인스턴스 변수를 필요로 하는 메서드
- 인스턴스 변수는 인스턴스(객체)를 생성해야만 만들어지므로 인스턴스 메서드 역시 인스턴스를 생성해야만 호출 가능
클래스 메서드(static 메서드)
- 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메서드를 사용하지 않는)메서드
- 인스턴스 변수를 사용하지 않는다고 해서 반드시 클래스 메서드로 정의해야하는 것은 아님(통상적으로 사용)
Static은 언제 사용하는가?
- 클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통으로 사용하는 것에 static을 붙임
- 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있음
- 클래스 메서드(static 메서드)는 인스턴스 변수를 사용할 수 없음
- 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려함
- static을 붙이면 메서드 호출시간이 짧아지므로 성능이 향상된다.
- static을 안 붙인 메서드(인스턴스 메서드)는 실행 시 호출되어야 할 메서드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다.
+) 추가적인 내용
메서드 간의 호출과 참조
- 같은 클래스에 속한 멤버들 간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다.
- 단, 클래스 멤버가 인스턴스 멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.
=> 인스턴스 멤버가 존재하는 시점에 클래스 멤버는 항상 존재하지만, 클래스 멤버가 존재하는 시점에 인스턴스 멤버가 존재하지 않을 수도 있기 때문
class TestClass {
void instanceMethod(){} //인스턴스 메서드
static void staticMethod(){} //static 메서드
void instanceMethod2(){ //인스턴스 메서드
instanceMethod(); //다른 인스턴스 메서드 호출
staticMethod(); //static 메서드 호출
}
static void staticMethod2(){
instanceMethod(); //error => 인스턴스 메서드를 호출할 수 없음
staticMethod(); // static메서드는 호출할 수 있음
}
}
-> staticMethod2()는 static메서드(클래스 메서드)이기 때문에 instanceMethod()를 호출할 수 없다.
class TestClass2{
int iv; //인스턴스 변수
static int cv; //클래스 변수
void instanceMethod(){ //인스턴스 메서드
System.out.println(iv); //인스턴스 변수를 사용할 수 있음
System.out.println(cv); //클래스 변수를 사용할 수 있음
}
static void staticMethod(){ //클래스 메서드
System.out.println(iv); //error! => 인스턴스 변수를 사용할 수 없음
System.out.println(cv); //클래스 변수는 사용할 수 있음
}
}
-> iv(인스턴스 변수)는 static메서드(클래스 메서드)에서 사용이 불가능하다.