수업 시작에 앞서..
오늘은 static 에 대해 얘기한다.
this 와 마찬가지로 static 역시 며칠동안 한 주제만 다룰 수 있을 만큼 할 얘기가 많지만 간추려서 다룰 것이다.
앞서서 이름이 같은 지역변수(매개변수)와 전역변수를 구분할 때 this 키워드를 언급한 적이 있었다.
이때 this 키워드를 만나면 그 위치를 감싸는 '클래스명' 과 같은 의미로 해석하며 전역 변수를 뜻한다고 설명했다. (여기서 전역변수 x는 static이 붙지 않았다고 가정한다.)
ex) this.x = x; // this.x는 전역변수, x는 지역변수(매개변수)
클래스명.x (Test103.x) 라 하지 않고 굳이 this.x 라 한 이유, this = 클래스명 이라고 해석하라는 이유가 있었다.
클래스명.변수 (Test103.x)는 static 변수에 접근하는 방법이기 때문이다!
클래스 변수, 클래스 메소드(static 변수, static 메소드)
변수와 메소드 앞에 static 키워드를 붙은 것을 각각 클래스 변수, 클래스 메소드라 부른다.
프로그램이 실행되면서 메모리를 할당받으며 프로그램이 끝날 때 까지 사용가능하다. 인스턴스 생성을 하지 않아도 클래스이름으로 접근하고 사용할 수 있다.
지금까지 class를 설계하면서 class 안에 변수를 선언하고 메소드를 정의해왔다. 하지만 이것들을 클래스 변수, 클래스 메소드라 부르지 않고 멤버 변수, 멤버 메소드라 불렀다. static이 붙은 클래스 변수, 클래스 메소드와 엄연히 다르므로 명칭에 혼동해서는 안된다.
★★static에 관해 반드시 숙지해야 할 키워드 2 가지
1. 공유 - 하나의 static 변수를 두고 객체들이 공유하여 접근, 사용한다.
2. 탄생 시점 - 로딩되는 순간 메모리가 할당된다. 즉, 『new』 연산자를 통해 메모리 할당을 받지 않아도(인스턴스가 생성되지 않아도) 사용이 가능하다.
* static과 non-static의 탄생 시점의 차이
프로그램을 실행시키면 먼저 설계도를 읽어들인다(class 로딩). 이때 static이 붙은 변수·메소드를 메모리에 할당된다. 프로그램이 시작되면 언제든지 사용, 호출할 수 있다.(main() 메소드도 static이다.)
프로그램이 실행되는 동안 new 키워드로 인스턴스를 생성하면 그제서야 non-static인 인스턴스 변수·메소드가 메모리에 올라간다. 인스턴스 생성이 되어야 non-static 멤버에 접근, 사용할 수 있다.
인스턴스 변수, 인스턴스 메소드(instance, non-static)
- static 키워드가 붙지 않은(non-static) 변수, 메소드.
- 인스턴스가 생성될 때 메모리에 할당을 받기 때문에 인스턴스가 생성되지 않고서는 접근, 사용이 불가능하다. 인스턴스가 생성된 이후부터 사용가능하며, 인스턴스를 통해서 접근할 수 있다.
- 생성된 인스턴스 별로 각각 존재하며 동일한 객체로 존재하는 인스턴스 메소드끼리는 사용, 호출이 가능하지만 클래스(static) 메소드에서는 접근할 수 없다.
클래스 변수, 클래스 메소드(static)
- 클래스 이름 또는 객체(인스턴스)를 통해 접근할 수 있다.
- 클래스 정보이기 때문에 로딩되는 순간 메모리 할당이 이루어진다.
- 클래스 변수나 클래스 메소드는 『생성된인스턴스명.변수명』, 『생성된인스턴스명.메소드명()』 의 형태로도 접근(호출)이 가능하지만 『클래스명.변수명』, 『클래스명.메소드명()』 의 형태로 접근(호출)하는 것이 일반적이다.
ex) Test103.a
예제 코드
/*=========================================================
■■■ 클래스와 인스턴스 ■■■
- 클래스 변수(static 변수)와 클래스 메소드(static 메소드)
=========================================================*/
// ※ 실습 편의상 접근제어지시자 생략
public class Test103
{
static int a = 10; //-- static 변수 / 클래스 변수 / class 변수 / 정적 변수
int b =20; //-- non-static 변수 / 인스턴스 변수 / instance 변수 (동적 변수라 하지는 않음)
void write() //-- non-static 메소드 / 인스턴스 메소드 / instance 메소드
{
System.out.println("클래스 변수 a : " + a);
System.out.println("인스턴스 변수 b : " + b);
}
static void print() //-- static 메소드 / 클래스 메소드 / class 메소드 / 정적 메소드
{
System.out.println("클래스 변수 a : " + a);
//System.out.println("인스턴스 변수 b : " + b);
//-- 에러 발생 (컴파일 에러)
//--==>> Test103.java:32: error: non-static variable b cannot be referenced from a static context
// 인스턴스가 생성되지도 않았는데 인스턴스 변수 b에 접근하려 함
}
public static void main(String[] args)
{
System.out.println("main() → 클래스 변수 a : " + Test103.a);
// 클래스 변수에는『클래스명.변수명』의 형태로 '클래스의 이름'을 통해 접근하는 것이 가능하다.
//--==>> main() → 클래스 변수 a : 10
System.out.println("main() → 클래스 변수 a : " + a);
//--==>> main() → 클래스 변수 a : 10
// 같은 클래스(Test103) 내부에 존재하기 때문에 클래스의 이름을 생략하는 것이 가능하다.
Test103.print();
print(); // 같은 클래스 안에 있으므로 클래스명 생략 가능
//--==>> 클래스 변수 a : 10
// 클래스 변수 a : 10
//-- 클래스 메소드에서 클래스 메소드의 호출은 가능하며,
// 『클래스명.메소드명()』의 형태로 접근하여 호출하는 것이 가능하다.
// 또한, 지금은 같은 클래스 내부에 존재하고 있는 상황이기 때문에
// 클래스의 이름을 생략하는 것이 가능하다.
//System.out.println("main() → 인스턴스 변수 b : " + b);
//System.out.println("main() → 인스턴스 변수 b : " + Test103.b);
// 인스턴스 변수는 클래스명으로 접근 불가능
//--==>> 에러 발생 (컴파일 에러)
//Test103.write();
//write();
//--==>> 에러 발생 (컴파일 에러)
// Test103 클래스 기반 인스턴스 생성
Test103 ob = new Test103();
//System.out.println("main() → 인스턴스 변수 b : " + b);
// 인스턴스 변수는 인스턴스를 통해 접근 가능하다.
//--==>> 에러 발생 (컴파일 에러)
// 생성된 인스턴스를 통해 인스턴스 변수에 접근하는 방법
System.out.println("main() → 인스턴스 변수 b : " + ob.b);
//--==>> main() → 인스턴스 변수 b : 20
// 생성된 인스턴스를 통해 인스턴스 메소드 접근(호출)
ob.write();
//--==>> 클래스 변수 a : 10
// 인스턴스 변수 b : 20
// 생성된 인스턴스를 통해 클래스 변수에 접근
System.out.println("main() → 클래스 변수 a : " + ob.a);
//--==>> main() → 클래스 변수 a : 10
// 생성된 인스턴스를 통해 클래스 메소드 접근(호출)
ob.print();
//--==>> 클래스 변수 a : 10
// ※ 클래스 변수나 클래스 메소드는
// 『클래스명.변수명』, 『클래스명.메소드명()』의 형태로 접근(호출)하는 것이 일반적이다.
System.out.println("main() → 클래스 변수 a : " + a);
System.out.println("main() → 클래스 변수 a : " + Test103.a);
System.out.println("main() → 클래스 변수 a : " + ob.a);
//--==>> main() → 클래스 변수 a : 10
// main() → 클래스 변수 a : 10
// main() → 클래스 변수 a : 10
System.out.println(); // 개행
// Test103 클래스 기반 인스턴스 생성
Test103 ob2 = new Test103();
ob2.a = 10000; //-- 클래스 변수 초기화
ob2.b = 20000; //-- 인스턴스 변수 초기화
System.out.println("ob2 확인 ---------------------------");
ob2.write();
//--==>> ob2 확인 ---------------------------
// 클래스 변수 a : 10000
// 인스턴스 변수 b : 20000
System.out.println("ob 확인 ---------------------------");
ob.write();
//--==>> ob 확인 ---------------------------
// 클래스 변수 a : 10000
// 인스턴스 변수 b : 20
}
}
'자바 풀스택 과정 수업 정리 > 자바' 카테고리의 다른 글
자바 14 (2020.08.21) : 정렬 알고리즘(선택, 버블, 삽입, 향상된 버블) (0) | 2020.08.28 |
---|---|
자바 13 (2020.08.20) : 메소드 오버로딩, 만년 달력, 주민번호 유효성 검사 (0) | 2020.08.24 |
자바 12-1 (2020.08.19) : 접근제어 지시자, 정보은닉, 캡슐화 (0) | 2020.08.23 |
자바 11-2 (2020.08.18) : 난수(Random 클래스), 배열의 복사 (0) | 2020.08.23 |
자바 11-1 (2020.08.18) : 배열의 배열(2차원 배열), 연습용 예제 (0) | 2020.08.23 |
최근댓글