본문 바로가기
study_java/java_수강정리(~10.29)

[JAVA]11일차

by developer_j 2020. 5. 25.
728x90
반응형

< 11일차 수업 >

 

class Circle {
           //인스턴스 변수 
           double radius = 0;

           //static 변수
           final static double PI = 3.14;
          
           //인스턴스 함수
           public Circle(double r) {
                       radius = r;
           }
          
           //아래 double getArea(){} 앞에 static 붙이면 radius에 빨간줄(에러남)
           //--> static 함수 안에 인스턴스 변수/함수가 올 수 없는 이유는 무엇일까?
          
           double getArea() {
                       double area = radius*radius*PI;
                       return area;
           }
           
}

 

1. static은 무엇인가?

static 키워드가 붙은 변수를 클래스 변수라 한다. static에 대해 제대로 이해하기 위해서는 데이터 영역도 함께 공부해줘야한다. 메모리 영역은 C언어의 경우 4가지 영역으로 나뉘고, java에서는 7가지 영역까지 있지만 3가지 영역에 대해서만 설명하겠다.

 

< 메모리 구조 발그림 >

 

1. static 멤버(변수, 함수)들은 메인함수가 포함된 클래스가 method 영역에 로딩되는 것과 거의 동시에, 그리고 함께 method 영역에 로딩된다.

1-1. static 멤버들은 로딩과 동시에 할당된 값/내용으로 초기화된다.

 3번 되뇌이고 다음 번호로 넘어가기!!!

2. 인스턴스 멤버(변수, 함수)들은 생성자를 호출하는 코드(new Constructor();)를 진행하면서 heap 영역에 생성된다.

2-1. 생성된 인스턴스의 주소값은 call-stack 영역에 생성된 참조형 변수의 메모리 공간으로 반환되며, 참조형 변수는 해당 인스턴스를 가리키게 된다.

2-2. heap 영역에 생성된 인스턴스 안에 method 영역에 존재하는 클래스 객체에 접근할 수 있도록, 자바 컴파일러가 method영역의 클래스 주소값을 살포시 넣어준다.

 3번 되뇌이고 다음 번호로 넘어가기!!!

3. 1번과 2번의 순서를 정리하자면, 인스턴스 생성 이전에 클래스 변수/함수가 메모리에 먼저 로딩된다.

그래서 클래스 함수에서 인스턴스 변수를 사용하고자 하면 컴퓨터가 "생성되지 않은 내용을 사용하여 함수를 진행할 수 없습니다"면서 에러를 발생시키는 것이다.

 

그니까, 데이터가 메모리에 형성되는 시기가 인스턴스보다 클래스 멤버가 더 빠르다. 더 먼저 생성되니까 나중에 생성되는 데이터를 미리 연산하거나 사용할 수 없다. 여기서 1-2번을 추가하겠다.

 1-2. 그래서 static 은 객체 생성을 하지 않아도 클래스명으로 접근 할 수 있다.(따로 생성된거니까 인스턴스 생성해서 생성한 인스턴스명으로 접근할 필요가 없다.)

 

중간 결론 : 클래스 멤버가 인스턴스보다 먼저 메모리에 정착하므로, 인스턴스 멤버를 사용하려는 클래스 함수는 에러가 발생한다. 

즉, static 함수안에서는 인스턴스 함수/변수를 사용할 수 없다. 그러나 인스턴스 함수는 static 함수/변수를 사용할 수 있다.(내용 추가 예정)

 

 이러한 특성 탓에, 클래스 변수는 인스턴스 별로 가지고 있을 필요가 없는 변수에 대해 static을 붙여서 선언해준다. 단순히 읽어들여서 비교를 한다거나 등의 값의 참조용도의 변수, 혹은 값이 공유되어야 하는 변수일 경우 클래스 변수로 선언한다. 클래스 함수도 단순 기능 제공이 목적인 메소드들(예를 들어 그냥 a+b의 결과값을 리턴하는 함수 등)이거나 상당히 자주 쓰는 함수나, 인스턴스 변수와 관련지을 이유가 없는 메소드들은 static으로 선언해주는 것이 좋다.

+)클래스 변수의 초기화는 클래스 처음에 해주어야 한다. 클래스 변수 초기화를 생성자에 선언해두면 인스턴스 생성시마다 변수값이 리셋되어 단순 생성자와 다를바 없으며 static으로 선언하는 의미가 없기 때문이다. 의미없는 코드를 짜지 말도록 하자.

 

반대로 말하면, 인스턴스 별로 가져야 되는 인스턴스 변수는 값이 객체별로 달라질 수 있는 변수일 경우 선언해준다는 것을 알 수 있다. 

 

그렇다면 static은 왜 사용하는가?

예를 들어 객체를 100개를 생성한다 치자. 그러면 인스턴스화를 위해 해당 객체 안에 들어있는 인스턴스 변수와 인스턴스 함수들도 똑같이 100개가 생성된다. 그러나 PI 값 등 절대 상수나 단순한 특정 값은 100개까지 생성할 필요가 없다. 그렇기 때문에 static으로 하나의 변수 값으로 선언해두고, 100개 이상의 객체가 그 값을 공유하면서 사용하도록 하는 것이다. 즉, static이라는 공유된 변수를 하나 선언해둠으로써 100개의 객체들이 PI만큼의 메모리를 절약할 수 있기 때문에 사용한다는 것이다.


클래스 멤버를 이해한다면 다음의 코드도 분석할 수 있다.

System.out.println(n);

System --> 클래스명. 자바기본 클래스에 정의되어 있다. public final class java.lang.System { ... }

out --> 클래스변수. 왜 변수냐고? 괄호()가 없으니까! 이것도 정의되어 있다. public final static PrintStream out = null; 참조형 변수

println --> 함수. 이것도 정의되어 있음. println(매개변수 n){print(n); newLine();}

 모두 자바 기본 클래스에 정의되어 있으며, import를 하지 않아도 객체 생성 없이 실행되는 이유는 자바 컴파일러가 알아서 자바 기본 클래스를 import 해주기 때문.

 

728x90
반응형

'study_java > java_수강정리(~10.29)' 카테고리의 다른 글

[JAVA]13일차  (0) 2020.05.27
[JAVA]12일차  (0) 2020.05.26
[JAVA]10일차  (0) 2020.05.22
[JAVA]9일차  (1) 2020.05.21
[JAVA]8일차  (0) 2020.05.20