티스토리 뷰

JAVA

[JAVA] 변수와 메소드

코헴 2019. 5. 22. 22:23

JVM 메모리 구조

  • 메소드 영역(method area)
    • 프로그램 실행중에 어떤 클래스가 사용되면 JVM은 해당 클래스의 클래스파일을 읽어서 클래스에 대한 정보를 이곳에 저장한다. 해당 클래스의 변수도 이곳에 저장된다.
  • 힙(heap)
    • 인스턴스가 생성되는 공간. 프로그램 실행 중 생성되는 인스턴스는 모두 이곳에 생성된다.
  • 호출스택(call stack)
    • 호출스택은 메서드의 작업에 필요한 메모리 공간을 제공한다.

기본형 매개변수와 참조형 매개변수

자바에서는 메소드를 호출할 때 매개변수로 지정한 값을 메소드의 매개변수에 복사해서 넘겨준다. 매개변수의 타입이 기본형(primitive type)일 때는 기본형 값이 복사되겠지만, 참조형(reference type) 이면 인스턴스의 주소가 복사된다.

메서드의 매개변수를 기본형으로 선언하면 단순히 저장된 값만 얻지만, 참조형으로 선언하면 값이 저장된 곳의 주소를 알 수 있기 때문에 값을 읽어오는 것은 물론 값을 변경하는 것도 가능하다.

class Data {
    int x;
}

class ParameterTest {
  public static void main(String[] args) {
    Data d = new Data();
    d.x = 10;
    System.out.println("main() : x = " + d.x);
    change(d.x);
    System.out.println("After change(d.x)");
    System.out.println("main() : x = " + d.x);
  }

  static void change(int x) {
    x = 1000;
    System.out.println("change() : x = " + x);
  }
}

/* 실행 결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 10
*/
class Data {
    int x;
}

class ParameterTest {
  public static void main(String[] args) {
    Data d = new Data();
    d.x = 10;
    System.out.println("main() : x = " + d.x);
    change(d.x);
    System.out.println("After change(d.x)");
    System.out.println("main() : x = " + d.x);
  }

  static void change(Data d) { // 참조형 매개변수
    d.x = 1000;
    System.out.println("change() : x = " + x);
  }
}

/* 실행 결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 1000
*/

배열을 통한 접근에서도 마찬가지로 배열은 객체와 같이 참조변수를 통해 데이터가 저장된 공간에 접근하므로 다음과 같은 결과를 얻는다

class ParameterTest {
  public static void main(String[] args) {
    int[] x = {10};
    System.out.println("main() : x = " + x[0]);
    change(x);
    System.out.println("After change(x)");
    System.out.println("main() : x = " + x[0]);
  }

  static void change(int[] x) { // 참조형 매개변수
    x[0] = 1000;
    System.out.println("change() : x = " + x[0]);
  }
}

/* 실행 결과
main() : x = 10
change() : x = 1000
After change(d.x)
main() : x = 1000
*/

클래스 메소드(= static method) 와 인스턴스 메소드

메소드 앞에 static 이 붙어있으면 클래스메소드이고 아니면 인스턴스 메소드이다.

클래스 메소드의 경우 객체를 생성하지 않고도 '클래스이름.메소드이름(매개변수)' 와 같은 방식으로 호출이 가능하다.

반면에 인스턴스 메소드는 반드시 객체를 생성해야 호출할 수 있다.

그렇다면 어느 경우에 static을 사용해서 클래스 메소드로 정의해야 하는 것일까?

클래스는 변수 + 변수와 관련된 메소드의 집합 으로 표현된다.

같은 클래스 내에 있는 메소드와 멤버 변수들은 아주 밀접한 관계가 있다.

인스턴스 메소드는 인스턴스 변수와 관련된 작업을 하는 즉, 메소드의 작업을 수행하는데 인스턴스 변수를 필요로 하는 메소드이다.

그래서 인스턴스변수는 인스턴스를 생성해야만 만들어지므로 인스턴스 변수를 사용하는 인스턴스 메소드 역시 인스턴스를 생성해야만 호출할 수 있는 것이다.

반면에 메소드 중에서 인스턴스와 관계없는(인스턴스 변수나 인스턴스 메소드를 사용하지 않는) 메소드를 클래스 메소드로 정의한다.

물론 인스턴스 변수를 사용하지 않는다고 해서 반드시 클래스 메소드로 정의해야 하는 것은 아니지만 특별한 이유가 없는 한 그렇게 하는 것이 일반적이다.

일반적으로 메소드를 정의할때 고려할 점을 나열하면 다음과 같다

  1. 클래스를 설계할 때 멤버변수 중 모든 인스턴스에 공통적으로 사용해야 하는 것에 static을 붙인다.
    • 생성된 각 인스턴스는 독립적이기 때문에 각 인스턴스 변수는 서로 다른 값이지만, 인스턴스 사이에서 같은 값이 유지되어야 하는 변수는 static을 붙여서 클래스 변수로 정의한다.
  2. 클래스 변수(static 변수)는 인스턴스를 생성하지 않아도 사용할 수 있다.
    • static이 붙은 변수는 클래스가 메모리에 올라갈 때 이미 자동적으로 생성되기 때문
  3. 클래스 메소드는 인스턴스변수를 사용할 수 없다.
    • static이 붙은 메소드는 인스턴스 생성 없이 호출 가능한 반면, 인스턴스 변수는 인스턴스를 생성해야만 만들어지기 때문에 static이 붙은 메소드를 호출할 때 인스턴스가 생성되어 있지 않을 수 있어서 static이 붙은 메소드에서 인스턴스 변수의 사용을 허용하지 않는다.
  4. 메소드 내에서 인스턴스변수를 사용하지 않는다면 static을 붙이는 것을 고려한다
    • 메소드의 작업 내용 중에서 인스턴스 변수를 필요로 한다면 static을 붙일 수 없다. 반대로 인스턴스 변수를 필요로 하지 않는다면 static을 붙이자. 메소드 호출시간이 짧아지기 때문에 효율이 높아진다. static을 안붙인 메소드는 실행시 호출되어야 할 메소드를 찾는 과정이 추가적으로 필요하기 때문에 시간이 더 걸린다.

참고 : Java의 정석(남궁 성 지음)

'JAVA' 카테고리의 다른 글

[JAVA] 변수의 초기화  (0) 2019.05.22
[JAVA] 생성자  (0) 2019.05.22
[JAVA]JVM구조 이해하기  (0) 2019.01.15
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함