정적(Static)
>> 정적 필드와 정적 메소드는 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 고정된 멤버이다. 그러므로 클래스를 로딩해서 메소드 메모리 영역에 적재할때 클래스별로 관리된다. 따라서 클래스의 로딩이 끝나는 즉시 바로 사용할 수 있다.
class Temp{
static int add( int i , int j ){ return 100; }
}
public class Main{
public static void main( String[] args ){
int r = Temp.add(10 , 20 );
System.out.println( r );
}
}
- static이 붙은 멤버함수는? '인스턴스 없이' 클래스명, 함수명으로 호출이 가능하다. (참조형 변수도 불필요)
- 클래스 안에서 선언하면서 멤버함수,변수와 구별되도록 static 이라는 키워드를 사용한다
class Temp {
static { // static initializer
System.out.println("static");
}
Temp() {
System.out.println("생성");
}
}
public class Main {
public static void main( String[] args ) {
new Temp();
new Temp();
new Temp();
}
}
/* 실행결과
static
생성
생성
생성
*/
- (static{}) 영역 : static initializer 라고 한다. 이 영역은 인스턴스 생성 이전에 딱 한번 호출된다. '클래스가 메모리에 로딩되는 시점에 JVM에 의해 호출된다.'
- 인스턴스를 아무리 많이 만들어도 클래스는 딱 한번만 인스턴스 생성 이전에 로딩된다. 인스턴스를 만들 때 멤버변수와 멤버함수를 가리키는 함수포인터는 메모리를 할당받게 된다.
- 즉 클래스가 로딩되는 시점에서는 멤버함수와 멤버변수를 호출할 수 없다.( 존재하지 않으므로 )
[ CASE ]
class Temp{
static { // 얼마든지 OK
Temp t = new Temp();
t.print();
}
static void print2() {
// print(); << 에러
}
void print(){
System.out.println("dd");
}
}
public class Main{
public static void main( String[] args ){
new Temp();
}
}
- 에러메세지 : non-static method print() cannot be referenced from a static context
- >> static 이 언급된 멤버변수와 함수가 생성되는 시점은 class 로딩할 때 이다. 근데 이 때는 non-static한 멤버들이 존재하기 전이다. 그러므로 static한 멤버 안에서 non-static 한 멤버는 직접 사용힐 수 없다.
[ CASE ]
interface ITemp{
// public static void print(); << 에러
}
- 인터페이스는 오버라이딩을 전제로 하는 함수여야 하고 오버라이딩은 함수포인터 형태로 운용되어야 하며, 그러려면 인스턴스에 함수포인터가 있어야하고 그러려면 non-static 해야한다.
- 그러므로 인터페이스 안에서는 non-static한 메소드를 써야 한다.
[ Singletone Pattern ]
class Temp {
private Temp() { // #1. 생성자 앞에 private 붙으면 Temp 밖에서는 생성자를 호출할 수 없다. 즉 인스턴스 생성도 안된다.
}
// # 2. uniq 변수는 jvm 안에 유일하게 존재한다.
private static Temp uniq = null;
// #3. static initializer 안에서 uniq로 인스턴스를 가리키게 하라.
static{
uniq = new Temp(); //클래스 '안'에서 private한 것을 이용할 수 있다.
}
// #4. public static synchronized 하게 uniq를 제공하는 getInstance 함수를 선언한다.
public static synchronized Temp getInstance(){
return uniq;
}
}
public class Main {
public static void main( String[] args ) {
// new Temp(); << 에러 발생 #1
Temp a = Temp.getInstance() ;
Temp b = Temp.getInstance() ;
System.out.println( a == b ); //하나의 인스턴스가 재활용되고 있고 공유되고 있음!!!
}
}
- JAVA에서 static을 이용해 인스턴스를 딱 하나만 jvm 상에 존재하게 할 수 있다.
- 이런 식으로 설계하는 설계패턴을 Singletone Pattern 이라고 한다.
'JAVA > 정리한 것' 카테고리의 다른 글
| [ JAVA ] 어노테이션( Annotation ) (0) | 2022.05.19 |
|---|---|
| [ JAVA ] class.forName() (0) | 2022.05.18 |
| [ JAVA ] 익명 클래스 ( Anonymous Class ) (0) | 2022.05.16 |
| [ JAVA ] 제너릭( Generic ) (0) | 2022.05.16 |
| [ JAVA ] Abstract 와 Interface (0) | 2022.05.15 |