개발자 취업준비/java

static 변수와 메서드

naspeciallist 2025. 1. 31. 23:29

1.static란?


 

객체지향 프로그래밍(OOP)에서 static 키워드는 클래스와 관련된 변수나 메서드를 정의하는 데 사용됩니다.

 

  • 일반적인 인스턴스 변수는 객체가 생성될 때 마다 메모리에 따로 할당됩니다. 하지만 staic 키워드가 붙은 변수는 메모리에 한번만 할당되며 프로그램이 종료 될 때 까지 유지됩니다.

※ static의 메모리 구조

 

일반적으로 우리가 만든 Class는 Static 영역에 생성되고 new 연산을 통해 생성한 객체는 Heap영역에 생성됩니다. 

객체 생성 시 할당된 Heap영역에 메모리는 Garbage Collector를 통해 관리를 받습니다. 하지만 Static 키워드를 통해 Static영역에 할당된 메모리는 모든 객체가 공유하는 메모리라는 장점이 있지만 Garbage Collector의 관리를 받지 않기 때문에 Staitc을 자주 사용하게 되면 프로그램 종료시 까지 메모리가 할당된 채로 존재하기 때문에 퍼포먼스에 악영향을 주게 됩니다. 

 

2. static 변수


  • staic 키워드가 붙은 변수는 클래스에 속하는 변수이며, 모든 인스턴스(객체)가 공유합니다.
  • 객체를 생성하지 않아도 클래스명으로 직접 접근 할 수 있습니다.

보통 클래스 안의 변수나 메서드를 사용하려면, 먼저 객체를 생성해야 합니다. 하지만 static 키워드가 붙으면 객체를 만들지 않아도 클래스명으로 직접 사용할 수 있습니다.

// 인스턴스 변수를 가지는 Person 클래스
class Person {
    String name = "홍길동";  
    void showName() {
        System.out.println("이름: " + name);
    }
}

// 정적 메서드를 관리하는 Person2 클래스
class Person2 {
    static String staticName = "김길동";  

    static void showStaticName() { 
        System.out.println("이름: " + staticName);
    }
}

public class Main {
    public static void main(String[] args) {
    
   		//static메서드가 아니므로 객체 생성 후에 사용가능
        Person personInstance = new Person();
        System.out.println(personInstance.name); 
        personInstance.showName();

        //static 메소드이므로 객체 생성 없이 사용 가능
        System.out.println(Person2.staticName);
        Person2.showStaticName();
    }
}

 

Static 변수는 메모리에 한번 할당되어 프로그램이 종료될 때 해제되는 변수입니다. 메모리에 한번 할당되므로 여러 객체가 해당 메모리를 공유하여 참조하게 됩니다.

 

예를 들어보겠습니다.

class Person {
    static String name = "홍길동";  
    
    void showName() {
        System.out.println(name);  // static 변수는 모든 객체가 공유
    }
}

public class Main {
    public static void main(String[] args) {
        // 100개의 Person 객체를 생성
        Person[] people = new Person[100];
        
        // 객체 100개 생성 및 저장
        for (int i = 0; i < 100; i++) {
            people[i] = new Person();
        }
        
        // 첫 번째 객체의 name을 변경
        people[0].name = "김길동";  // static 변수는 모든 객체가 공유하므로, 첫 번째 객체에서 변경하면 모든 객체에 영향을 미침
        
        // 모든 객체에서 name 출력 (모든 객체가 동일한 static 변수 참조)
        for (int i = 0; i < 100; i++) {
            people[i].showName();  // "김길동" 출력됨
        }
    }
}

 

 

예를 들어 name이라는 static변수를 선언 한 뒤 배열을 생성하여 100개의  객체를 생성하였습니다.

만약 위 코드에서 static을 사용하지 않고 100개의 객체를 생성하였으면 "홍길동"이라는 같은 값을 갖는 메모리가 100개나 중복해서 생성되게 됩니다. 하지만 static을 사용하면 여러객체가 하나의 메모리만 참조하기 때문에 "홍길동"이라는 값을 같는 메모리는 한개만 존재하게 됩니다. 

 

또한 100개의 객체들은 "홍길동"이라는 값을 가지고 있는 한개의 메모리만 참조하게 됩니다. 따라서 만약에 한개의 객체의 값이 "김길동"으로 변하게 되면 나머지 99개의 참조하고 있던 객체들의 값이 김길동으로 바뀌게 됩니다.

 

그러나 일반적으로 static 변수는 상수의 값을 갖는 경우가 많습니다. public 및 final과 함께 사용되어 값이 바뀌는 일은 거의 없습니다.

 

3. static 메서드(정적 메서드)


static 메서드는 클래스에 속하는 메서드로, 객체를 생성하지 않고 클래스명으로 바로 호출할 수 있는 메서드입니다.

 

  • static 메서드는 클래스 메서드라고도 불리며, 클래스가 메모리에 로드될 때 함께 로드됩니다.
  • 객체 없이 클래스명으로 호출할 수 있습니다.
  • static 메서드는 인스턴스 변수(즉, 객체가 생성되어야만 사용 가능한 변수)에 접근할 수 없으며, 오직 static 변수만 접근 가능합니다.

일반적으로 유틸리티 관련 함수들은 여러번 사용되므로 static 메소드로 구현을 하는게 적합한데, staitc메소드를 사용하는 대표적인 Util Class로는 java.util.Math가 있습니다.

import java.util.*;

class MathUtils {
    // static 메서드
    static int add(int a, int b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
    
        int a = 20;
        int b = 15;
        System.out.println("합: " + MathUtils.add(a, b));
        System.out.println("더 큰 값: " + Math.max(a, b));  // 20
        System.out.println("더 작은 값: " + Math.min(a, b));  // 15
        
    }
}

 

 

4. Utility클래스에서 static을 사용하는 이유


 

Java Utility 클래스는 공통적으로 사용되는 기능을 묶어놓은 클래스 입니다. 예를 들어 Math,Collections,Arrays 같은 자바의 표준 유틸리티 클래스가 있습니다. 이런 클래스들은 객체를 생성 할 필요 없이 공통적으로 사용할 수 있어야 하므로 static으로 선언하는 것이 일반적 입니다.

 

 또한 유틸리티 클래스의 메서드는 상태를 가지지 않고, 항상 같은 기능을 수행 합니다. 쉽게 설명하면 유틸리티 클래스는 단순히 기능만 제공하는 클래스입니다. 그렇기 때문에 특정 데이터를 저장하거나 변경하지 않고 매번 같은 동작을 수행해야합니다. 따라서 객체를 생성하는 것은 불필요한 행동이며, 메모리를 낭비 할 수 있습니다. 즉 객체를 생성하는 것이 불필요 하며, 메모리를 절약하기 위해 static을 사용합니다.

 

 

Utility 클래스에서 public final을 사용하는 이유

유틸리티 클래스는 위에서 설명한 것처럼 메서드(기능)만 제공하고, 객체가 상태(데이터)를 가질 필요가 없습니다.

따라서 클래스를 상속 받아서 확장 할 필요가 없습니다. 만약 유틸리티 클래스에 final을 사용하지 않으면 상속이 가능해집니다. 만약 유틸리티 클래스에 final을 사용하지 않아 상속이 가능해지면 다음과 같은 문제점들이 발생합니다.

 

  • 유틸리티 클래스의 원래 목적과 다르게 하위 클래스에서 멋대로 기능을 추가할 수 있음
  • 코드가 예측할 수 없는 방식으로 확장될 위험이 있음

 

 

 

5. static메서드의 제한사항


 

1. this 키워드 사용 불가: static 메서드는 객체에 속하지 않기 때문에, this 키워드를 사용할 수 없습니다.

 

2. 다형성 제한: static 메서드는 다형성을 지원하지 않습니다. 즉, 오버라이딩이 불가능하며, 서브클래스에서 static 메서드      를 재정의할 수 없습니다.

 

3.인스턴스 변수와 메서드에 접근 불가: static 메서드는 객체에 속하지 않으므로 인스턴스 변수나 인스턴스 메서드에 직접 접근할 수 없습니다.

 

코드로 예를 들어보겠습니다.

class Person {
    String name = "홍길동";  // 인스턴스 변수
    static String staticName = "김길동";  // static 변수

    static void showName() {
        // System.out.println("이름: " + name);  // 오류 발생: 인스턴스 변수 접근 불가
        System.out.println("Static 이름: " + staticName);  // 정상 실행 (static 변수 접근 가능)
    }
}

 

static으로 선언된 메서드 내부에서 static으로 선언된 변수 staticName은 접근이 가능하지만 인스턴스변수인 name은 접근이 불가능한 것을 확인 할 수 있습니다. 인스턴스변수가 static메서드에 접근하지 못하는 이유는 메모리의 구조차이 때문입니다. static메서드와 static 변수는 클래스가 로드될 때 메모리의 static 영역에 할당 됩니다. 그에 비해 인스턴스 변수는 객체가 생성될 때 힙(Heap)메모리에 저장이 됩니다. 따라서 static 메서드는 객체의 생성 여부와 상관없이 존재하므로, 아직 생성하지 않은 인스턴스 변수를 참조 할 수 없습니다.

 

class Person {
    String name = "홍길동";  // 인스턴스 변수
    static String staticName = "김길동";  // static 변수

    static void showName() {
    	Person person = new Person();  // 객체 생성
        System.out.println("이름: " + name);  
        System.out.println("Static 이름: " + staticName);
    }
}

 

객체를 생성한다면 이제 staitc메서드 내부에서도 인스턴스 변수에 접근할 수 있습니다.

'개발자 취업준비 > java' 카테고리의 다른 글

Optional이란?  (0) 2025.03.25
[java] 자료(Data)와 자료형(Data Types)  (1) 2025.01.30
HaspMap 충돌과 해결방법  (2) 2025.01.23