메모리 구조
자바의 메모리는 크게 아래 세가지로 나눌 수 있다.
- 메서드 영역: 클래스 정보를 보관. (붕어빵 틀)
- 스택 영역: 프로그램이 실행되는 영역 (프로그램이 실행되는 방식을 생각해보면 stack 방식이라는 것을 알 수 있을 것이다.)
- 힙 영역: 인스턴스(객체)가 생성되는 영역 (붕어빵)
Static 변수
인스턴스(객체)를 생성하면 그 객체 각각의 변수가 생성된다. 하지만
개발을 하다보면 인스턴스(객체) 들의 공용 데이터가 필요할 때가 있다.
이러한 경우에 static을 통하여 공용 데이터를 만들수 있다.
아래는 몇개의 인스턴스(객체)가 생성되었는지를 출력하는 코드이다.
class Counter {
// static 변수
private static int count = 0;
// 생성자: 객체가 생성될 때마다 count 증가
public Counter() {
count++;
}
// static 메서드: count 값 반환
public static int getCount() {
return count;
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Counter obj1 = new Counter();
Counter obj2 = new Counter();
Counter obj3 = new Counter();
// static 메서드를 호출하여 count 값 출력
System.out.println("Number of objects created: " + Counter.getCount()); // 출력: 3
}
}
다음과 같이 static 변수(공용변수)를 이용하여 인스턴스(객체)가 생성된 개수를 출력할 수 있다.
그러면 Static 변수에 접근하는 방법을 알아보자.
class Counter {
// static 변수
public static int count = 0;
// 생성자: 객체가 생성될 때마다 count 증가
public Counter() {
count++;
}
}
public class Main {
public static void main(String[] args) {
// 객체 생성
Counter obj1 = new Counter();
Counter obj2 = new Counter();
Counter obj3 = new Counter();
// static 변수에 접근
System.out.println("Number of objects created: " + Counter.count); // 출력: 3
}
}
위 코드에서 볼수 있듯이 static 변수에 접근할때는 (Counter.count)와 같이 클래스명에 .(dot)을 사용한다.
이는 static 이 붙은 멤버변수는 인스턴스 영역(힙 영역)이 아닌 메서드 영역에 생성되기에 그렇다.
멤버 변수의 종류
- 인스턴스 변수: static이 붙지 않은 멤버 변수(인스턴스를 생성해야 사용 가능)
- 클래스 변수: static이 붙은 멤버 변수(클래스 변수, 정적 변수, static변수라 불리며, 클래스에 바로 접근해서 사용가능하다.)
Static 메서드
static 메서드는 static 변수와 같이 공용 메서드이며 인스턴스 생성 없이 클래스 명을 통해 사용가능하다.
class Calculator {
// static 메서드: 두 숫자의 합을 반환
public static int add(int a, int b) {
return a + b;
}
// static 메서드: 두 숫자의 차를 반환
public static int subtract(int a, int b) {
return a - b;
}
}
public class Main {
public static void main(String[] args) {
// static 메서드를 클래스명으로 직접 호출
int sum = Calculator.add(5, 3);
int difference = Calculator.subtract(10, 4);
System.out.println("Sum: " + sum); // 출력: Sum: 8
System.out.println("Difference: " + difference); // 출력: Difference: 6
}
}
다음 코드에서 볼수 있듯이 객체를 생성하지 않고 메서드를 상요하는 것을 확인할 수 있다.
제약
static 메서드 에서는 instance 변수 / 메서드에 접근하는 것이 불가하다.
(단, parameter로 instance 의 참조값을 받는경우는 가능!)
class Example {
// 인스턴스 변수
private int instanceVar = 10;
// 인스턴스 메서드
public void instanceMethod() {
System.out.println("This is an instance method.");
}
// static 메서드
public static void staticMethod() {
// 인스턴스 변수 접근 시도 - 오류 발생
System.out.println("Instance variable: " + instanceVar); // 오류 발생
// 인스턴스 메서드 호출 시도 - 오류 발생
instanceMethod(); // 오류 발생
}
}
public class Main {
public static void main(String[] args) {
// static 메서드 호출
Example.staticMethod();
}
}
다음 코드처럼 static 메서드에서는 instance 변수 / 메서드에 접근 불가하다.
instance 변수는 인스턴스(객체)가 생성되어야 접근 가능하고 참조값이 생성되는데, static 메서드에서는 접근할 참조값도, 객체가 생성되었는지 여부도 알수 없기에 접근이 불가하다.
final
final 키워드를 붙으면 더 이상 값을 변경할 수 없다.
- final 변수는 변수의 값을 한 번만 설정 가능하며, 이후에 변경이 불가하다.
- final 메서드는 하위 클래스(자식 클래스)에서 오버라이딩할 수 없다.
- final 클래스는 다른 클래스가 해당 클래스를 상속할 수 없다.
아래는 예시코드이다.
// 1. final 변수
class FinalVariableExample {
public static void main(String[] args) {
final int CONSTANT_VALUE = 100;
System.out.println("Initial Value: " + CONSTANT_VALUE);
// CONSTANT_VALUE = 200; // 오류: final 변수는 값을 다시 할당할 수 없음
}
}
// 2. final 메서드
class Animal {
final void sound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
// @Override
// void sound() { // 오류: final 메서드는 오버라이딩할 수 없음
// System.out.println("Bark");
// }
}
// 3. final 클래스
final class FinalClass {
void display() {
System.out.println("This is a final class.");
}
}
// class SubClass extends FinalClass { // 오류: final 클래스는 상속할 수 없음
// }
public class Main {
public static void main(String[] args) {
FinalVariableExample.main(args);
Animal animal = new Animal();
animal.sound();
FinalClass finalClass = new FinalClass();
finalClass.display();
}
}
'인프런 - 백엔드(김영한) > java' 카테고리의 다른 글
상속 (1) | 2024.11.09 |
---|---|
접근 제어자 (4) | 2024.10.17 |
class / 객체 (0) | 2024.10.11 |
배열 (0) | 2024.10.08 |
형변환 (0) | 2024.10.06 |