[JAVA] static 키워드 & 컴퓨터의 메모리 구조

:-)·2022년 4월 18일
1

☕ JAVA

목록 보기
8/15
post-thumbnail

📝 static

  • static은 '고정된' 또는 '공통적인'의 의미를 가지고 있다.
    즉 모든 객체가 공유하는 값이다.
  • static 값은 클래스 이름을 통해서 접근해야 하며, 객체를 생성하지
    않고도 사용할 수 있다.

static 예시

하나의 게시물을 표현하기 위한 클래스가 있다.

public class Article{
	private int num;			// 글 번호
	private String title;		// 제목
	private String regDate;		// 날짜	
}

이 클래스에 게시물이 새로 등록될 때 마다, 전체 글 수를 의미하는 count, 카테고리 정보를 담을 변수를 추가 할려고 한다.

public class Article{
	int count; 			// 전체 글 수		
	String category;	// 카테고리

	private int num;			// 글 번호
	private String title;		// 제목
	private String regDate;		// 날짜	
}

이렇게 전체 글 수, 카테고리정보를 선언한 후 여러 객체를 생성할 때
다음과 같은 문제가 발생한다.

public class Main {

	public static void main(String[] args) {
		Article a1 = new Article(1, "첫번째 글제목", "20XX-01-01");
		a1.category = "공지사항";
		a1.count++;
		
		Article a2 = new Article(2, "두번째 글제목", "20XX-01-02");
		a2.category = "공지사항";
		a1.count++;
		a2.count = a1.count;
				
		Article a3 = new Article(3, "세번째 글제목", "20XX-01-03");
		a3.category = "공지사항";
		a1.count++;
		a2.count++;
		a3.count = a2.count;
		
		System.out.println(a1.toString());
		System.out.println(a2.toString());
		System.out.println(a3.toString());
	}

}

👉 실행 결과

Article [count=3, category=공지사항, num=1, title=첫번째 글제목, regDate=20XX-01-01]
Article [count=3, category=공지사항, num=2, title=두번째 글제목, regDate=20XX-01-02]
Article [count=3, category=공지사항, num=3, title=세번째 글제목, regDate=20XX-01-03]

이 코드처럼 객체를 생성할 때마다 count, category 변수들을 바꿔줘야 하는 번거로움이 생긴다.
또한 반복적인 코드가 많아서 좋지 못한 코드라고 볼 수 있다.


멤버변수는 모든 객체가 독립적으로 갖는 고유 데이터이기 때문에 count 라는
공유 데이터를 모든 게시물이 갖게 된다.
즉, 각각의 객체가 중복된 데이터를 갖게 된다.

이러한 문제를 해결하려면 다음과 같다.

모든 객체에서 공통적으로 사용해야 하는 값에 'static'을 붙인다.

public class Article{
	static int count; 				// 전체 글 수		
	static String category;			// 카테고리

	private int num;				// 글 번호
	private String title;			// 제목
	private String regDate;			// 날짜	
}

static이 붙은 멤버변수는 객체의 개수에 상관 없이 단 하나만 생성되며,
이를 모든 객체가 공유하기 때문에 메모리를 효율적으로 사용할 수 있다.

<static이 붙은 멤버변수를 사용할 땐 대문자로 쓴 클래스 이름을 사용하면 된다.>

public class Main {

	public static void main(String[] args) {
		Article.category = "공지사항";
		
		Article a1 = new Article(1, "첫번째 글제목", "20XX-01-01");
		Article.count++;
		
		Article a2 = new Article(2, "두번째 글제목", "20XX-01-02");
		Article.count++;
				
		Article a3 = new Article(3, "세번째 글제목", "20XX-01-03");
		Article.count++;
		
		System.out.println(a1.toString());
		System.out.println(a2.toString());
		System.out.println(a3.toString());
	}

}

많이 깔끔해졌지만 Article.count++; 매번 해줘야 하는 번거로움이 있다.
-> 객체가 생성될 때마다 Article.count가 1씩 증가되기 때문에 아예 생성자에 이 줄을 넣으면 된다.


✍ 최종 코드

public class Article {
	static int count; 			// 전체 글 수		
	static String category;		// 카테고리

	private int num;			// 글 번호
	private String title;		// 제목
	private String regDate;		// 날짜
	
	public Article(int num, String title, String regDate) {
		this.num = num;
		this.title = title;
		this.regDate = regDate;
		
		count++;
	}
    
    public String toString() {
		return "Article [count=" + count 
				+ ", category=" + category 
				+ ", num=" + num 
				+ ", title=" + title 
				+ ", regDate=" + regDate + "]";
	}
}    
public class Main {

	public static void main(String[] args) {
		Article.category = "공지사항";
		
		Article a1 = new Article(1, "첫번째 글제목", "20XX-01-01");
		Article a2 = new Article(2, "두번째 글제목", "20XX-01-02");
		Article a3 = new Article(3, "세번째 글제목", "20XX-01-03");
		
		System.out.println(a1.toString());
		System.out.println(a2.toString());
		System.out.println(a3.toString());
	}

}

👉 실행 결과

Article [count=3, category=공지사항, num=1, title=첫번째 글제목, regDate=20XX-01-01]
Article [count=3, category=공지사항, num=2, title=두번째 글제목, regDate=20XX-01-02]
Article [count=3, category=공지사항, num=3, title=세번째 글제목, regDate=20XX-01-03]



멤버변수와 static 멤버변수의 차이

  • 멤버변수는 객체가 생성될 때 마다 생성되므로 객체마다 각기 다른
    값을 유지할 수 있다.

  • static 변수는 모든 객체가 하나의 저장공간을 공유하므로, 항상
    공통된 값을 갖는다.

  • static 변수는 객체가 생성되지 않았더라도 이미 존재하고 있기 때문에 객체의
    이름을 통해 접근하는 것이 아니라, 클래스의 이름을 통해서 접근해야 한다.

    • 단, static 변수가 선언된 클래스 안에서는 변수 이름으로 직접 접근이 허용된다.
// Article 클래스 및 다른 클래스에서 접근하는 경우
	Article.count = 9;
	Article.categoty = "공지사항";

// Article 클레스에서 접근하는 경우
	count = 15;
	categoty = "Q&A게시판";


📝 컴퓨터의 메모리 구조

  • 컴퓨터의 운영체제는 프로그램의 실행을 위해 다양한 메모리 공간을 제공하고 있다.
  • 메모리 공간은 다음과 같은 4가지 영역으로 나누어진다.


코드 영역 (고정영역)

  • 프로그램의 코드가 저장되는 영역
  • 이 영역에 저장된 명령어들을 CPU가 하나씩 가져가 실행한다.

데이터 영역 (고정영역)

  • 전역변수와 static으로 선언되는 변수가 할당된다.
  • 이 영역에 할당되는 변수들은 프로그램 시작과 동시에 메모리 공간이 할당되어
    종료될 때 까지 남아있게 된다.

힙 영역 (동적영역)

  • 프로그래머가 원하는 시점에 변수를 할당하고 소멸시키는 영역
  • 메모리 동적 할당시 사용된다.
  • 객체가 생성되는 영역이다.

스택 영역 (동적영역)

  • 함수가 실행될 때 사용되는 파라미터와 지역변수에 대한 메모리 공간
  • 함수의 종료와 함께 소멸된다.



하나의 프로그램이 사용하는 메모리 영역

  • 고정영역

    • 프로그램이 실행되면 실행파일이 메모리에 로드되면서,
      실행파일의 용량만큼 RAM을 사용한다.

    • 실행 파일의 크기는 변할 수 없으므로 이 영역의 크기는 고정 크기를 갖는다.

    • 이 영역의 자원들은 프로그램이 실행되는 동안 항상 존재한다.

  • 동적영역

    • 프로그래머가 new 키워드를 사용해서 객체나 배열을 생성하면 사용된다.
      (힙 영역)

    • 메서드가 호출되는 동안 사용될 파라미터와 지역변수가 생성된다. (스택영역)

    • 메서드가 종료되거나 객체가 더 이상 사용되지 않으면 생성된 변수나
      객체는 메모리에서 사라지므로, 이 영역은 유동적인 크기를 갖게 된다.


프로그램이 메모리를 사용하는 순서

  • 최초 실행 시 고정 영역에 실행파일만큼의 메모리를 점유한다.
  • 프로그램이 각종 동작을 수행하는 동안 동적영역을 사용한다.

💥 static 메서드 & static 변수

  • 메모리 영역의 차이 때문에 static 메서드는 동적 메모리 영역의
    멤버변수를 사용하거나, static이 아닌 일반 멤버변수를 호출할 수 없다.

  • 메서드의 정의 과정에서 static 키워드를 사용하면 static 자원에 접근하기
    위한 메서드를 만들 수 있다.

  • 고정 영역

    • 동적 메모리 영역의 자원들은 항상 존재하는 것이 아니기 때문에
      static 멤버함수는 동적 메모리 영역의 멤버변수를 사용하거나,
      static이 아닌 일반 멤버함수를 호출할 수 없다.
  • 동적 영역

    • static 자원은 항상 존재하는 것이므로 동적 영역에서는 static 변수를
      활용하거나, static 멤버함수를 호출할 수 있다.
public class Article{
		private static int count;

		public static void setCount(int count) {
			Article.count = count;
		}

		public static int getCount() {
			return Article.count;
		}

	}



📙 정리

대상의미
멤버변수- 모든 객체에 공통적으로 사용되는 클래스 변수가 된다.
- 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능하다.
- 클래스가 메모리에 로드될 때 생성된다.
메서드- 객체를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
- static메서드 내에서는 인스턴스멤버들을 직접 사용할 수 없다.

static을 언제 붙여야 할까?

  • 멤버변수 중 모든 객체에 공통으로 사용하는 것에 static을 붙인다.
  • 메서드 내에서 인스턴스 변수나 인스턴스 메서드를 사용하지 않는 메서드에
    staitc을 붙이는 것을 고려한다.

0개의 댓글