JAVA/BASIC

Static 정적 멤버(변수,메서드 등)

유혁스쿨 2021. 5. 9. 00:28
728x90
반응형

 

* 메모리 영역별 그림은 추후에 꼭 추가하여 예시 별로 이해를 돕도록 할 예정입니다. *

 

클래스(static정적)/인스턴스 메서드가 생성되는 메모리 영역차이와 호출할때 접근방식에 따른 시간적 효율

 

메서드 호출법


#.직접호출

메서드명(인자값) : 내 자신(메인) 클래스 내에 정적 메서드를 선언해주면

메인클래스내의 정적 메인 메서드에서 직접적인 호출 즉, 메서드명(인자값); 호출이 가능해집니다.

public class StaticEx2 { public static String method(){ return "궁찬이"; } public static void main(String[] args) { /* main메서드 내에서 같은 클래스(내 자신 클래스)의 필드 메서드 (static메서드)의 호출형태. 클래스와 객체로의 접근 없이 메서드명(); 그대로 호출이 된다 */ method(); // 컴파일 에러 없음을 확인. (출력해주는 기능이 없으므로 문자열만 반환된 상태이다.) System.out.println(method()); //궁찬이 출력 } }

public class StaticEx2 { 
    public static String method(){ 
        return "궁찬이"; 
    } public static void main(String[] args) { 
        /* main메서드 내에서 같은 클래스(내 자신 클래스)의 필드 메서드 (static메서드)의 호출형태.
        클래스와 객체로의 접근 없이 메서드명(); 그대로 호출이 된다 */ 
        
        method(); // 컴파일 에러 없음을 확인. (출력해주는 기능이 없으므로 문자열만 반환된 상태이다.) 
        System.out.println(method()); //궁찬이 출력 
        } 
    }

 

정적메서드는 클레스에서 관리하기 때문에 같은 클래스내에서 직접 호출합니다.

(동일한 클래스에서 다시 또 클래스를 통해서 호출 할 필요가 없으니까요?)

 

# 클래스명.메서드명(){}  (X) | 메서드명(인자값);  (O)

 

 

#.간접호출

 

1. 정적메서드 (클래스) : 내 자신 클래스 내에서만 직접 접근이 가능합니다.

(같은 클래스명 내에서는 클래스명.을 생략가능)

스태틱 키워드가 붙은 정적 메서드가 클래스에 선언되면 메모리 영역은 해당 클래스의 바깥

즉, 클래스의 메모리영역과 같은영역 안에 생성 됩니다(메소드영역)

정적메서드는 선언된 해당 위치의 클래스가 관리합니다.(이는 클래스와 같은 영역임을 뜻함)

객체를 통해서도 이론상으로는 접근이 가능하지만 오래걸립니다.

정적 메서드와 클래스는 동일한 메모리영역 (메서드 영역)에 위치합니다.

그러므로 클래스를 통한 간접호출을 해야 시간손실이 최소화 됩니다.

 

# 클래스명.메서드명(인자값);  빠름

# 객체명.메서드명(인자값);  느림 : 객체-힙 / 클래스, static-메서드 |

 

2. 인스턴스메서드(객체) : 인스턴스 메서드는 각종 인스턴스 객체들이 저장되는 힙 영역에 메모리 영역이 생성됩니다.

그러므로 인스턴스 메서드는 인스턴스 객체를 통해 간접호출 하는게 빠릅니다.

클래스를 통해서도 이론상으로는 접근이 가능하지만 마찬가지로 오래걸린다. 인스턴스메서드와 객체는 동일한 메모리영역(힙 영역)에 위치합니다.

그러므로 객체 생성해 객체를 통해 간접호출하는것이 시간손실이 최소화됩니다.

 

# 객체명.메서드명(인자값);  빠름

# 클래스명.메서드명(인자값);  느림 : 객체-힙 / 클래스, static-메서드

 

class InstanceEx{ 
    public void instanceMethod(){ 
    System.out.println("--instanceMethod 호출"); 
    System.out.println("이 메서드는 인스턴스 메서드 이므로"); 
    System.out.println("메서드가 선언되어있는 클래스의 객체를 생성하여"); 
    System.out.println("객체명으로 접근하여 호출해야한다. "); 
        } 
    } 
    
public class StaticInstance {
    static void classMethod(){ 
    System.out.println("--classMethod 호출"); 
    System.out.println("이 메서드는 클래스(static정적) 메서드 이므로"); 
    System.out.println("메서드가 선언되어있는 클래스명으로 접근하여 호출해야한다. "); 
    } 
    
    public static void main(String[] args) {
// #정적 메서드 호출법 
        StaticInstance.classMethod(); //클래스명.메소드(); 로 클래스(static정적) 메서드 호출. 
        //main메소드에서 내 자신클래스의 필드에 선언된 메서드를 호출하기 위해서는 메서드를 정적화 시켜야한다.

// #인스턴스 메서드 호출법 
        InstanceEx instance = new InstanceEx(); 
        instance.instanceMethod(); //객체명.메소드(); 로 인스턴스 메서드 호출. 
    } 
}

 

메인메서드는 정적메서드이고 위에작성한코드는 인스턴스이므로 바깥영역메모리에 생성이됩니다.

메인 정적 메서드에서는 인스턴스 메서드를 호출할 수 없습니다.

스태틱 키워드를 붙혀 클래스 소속으로 정적메서드를 만들 수 있으나 프로그램이 무거워지므로 따로 클래스를생성하여 인스턴스 메서드를만들고, 객체를통해 해당 인스턴스메서드에 접근해야합니다.

 

class Static{ 
    public static int a; //값을 저장 하지 않아도 스태틱 메모리영역의 공간을 만든다. (힙영역일까?)
    public int b; //값을 저장하기 전까지 메모리영역을 차지하지 않는다.
}
public class StaticEx { 

    public static void main(String[] args) { 
    //Static클래스의 객체를 각각 A와 B 이름으로 두개 생성한다 
        Static objA = new Static(); 
        Static objB = new Static(); 
        
        objA.a=1; // 객체로 접근하면 이클립스상에서 추천해 주지 않는다고 변수명 아래에 노란밑줄을 띄운다 
        //(정적 변수이므로 인스턴스 변수로 접근하면 속도가 느려진다. 정적메서드는 클래스영역에,,) 
        System.out.println("A.a = " + objA.a); //1
        System.out.println("B.a = " + objB.a); //1 

/* 정적 변수는 값이 저장되지 않아도 해당 변수를 선언하는 순간 
메모리영역에 공간을 만들기때문에 객체로 접근하여 값을 한번 저장하면 
다른객체로 접근했을때 같은 값을 가져온다. 
즉, 서로다른객체끼리 값을 공유 할 수있게된다. 
A객체로 값을 저장후 B객체로 접근하여 값이 동일한지 확인해 본 후 
B객체로 임의의 수로 값을 초기화 해주고 A객체로 접근했을때 
초기화된 값이 출력되는지 확인해보자. */ 

        //Static변수의 객체간 데이터 공유 확인 
        objB.a=2; //a변수의 값을 2로 초기화 
        System.out.println("A.a = " + objA.a); //2 
//인스턴스변수의 객체간 데이터 공유 확인 
objA.b=1; 
        System.out.println("A.b = " + objA.b); //1 
        System.out.println("B.b = " + objB.b); //0(default) 
        
/* 추가로 static변수는 정적 변수이기때문에 
해당 클래스의 클래스명 으로 접근해야 속도가 빠르다. */ 
        System.out.println("Static 정적 변수의 올바른 접근 : " + Static.a); 
    } 
}

 

static 이라는 정적 키워드가 붙으면 값을 저장하지 않더라도 스태틱 메모리영역의 공간을 만듭니다

따라서 서로다른 두 객체로 해당 스태틱 변수에 접근을하면 객체끼리 공유할수있는 하나의 변수가 됩니다

인스턴스 변수는 값을 저장하지 않고 선언만 했을때 메모리영역이 생성되지않습니다

따라서 서로다른 두 객체로 하나의 인스턴스 변수에 접근하면 메모리영역이 각각 달라서 변수가 공유가되지 않습니다.

 

스태틱키워드를 붙혀 해당 클래스 소속으로 정적메서드를 만든 후 해당 클래스명으로 직접 접근해야만 빠른작업을 수행할수있으나 [예) 클래스명.메서드(인자값);]

스태틱 정적메서드는 해당 클래스안의 프로그램이 시작할때부터 종료되기전까지 메모리영역에 남아있으므로 프로그램이 무거워집니다

따라서 따로 클래스를생성하여 인스턴스 메서드를만들고, 객체를통해 해당 인스턴스메서드에 접근 해야 합니다. 

[예) 객체명.메서드(인자값);]

 

스태틱은 함부로 선언하지 말것.

 

 

 

728x90
반응형