3 minute read

인스턴스 메서드

특징

  • 클래스의 인스턴스로만 호출될 수 있다.
  • 클래스의 정적 필드와 인스턴스 필드에 모두 접근할 수 있다.
  • 메서드를 호출하는 인스턴스를 가리키는 this 키워드를 사용할 수 있다.
  • 새로운 인스턴스를 생성할 때 마다 메모리에 로딩된다.

유스 케이스

  • 각각의 인스턴스들에 특정된 작업을 수행할 목적으로 정의된다.
  • 메서드의 작업이 객체의 상태에 따라 좌우될 때
  • 객체의 필드를 수정할 때
  • 비즈니스 로직 등 애플리케이션의 핵심 로직을 수행할 때

➕인스턴스 메서드는 인스턴스에 속하고, static 메서드는 클래스 자체에 속한다?

  • 위의 문구는 인스턴스 메서드와 static 메서드를 설명할 때 흔하게 접할 수 있는 문구다. 그러나 인스턴스 메서드도 클래스에 정의되어 있다. 내 눈에는 사실상 “인스턴스 메서드든 static 메서드든 클래스에 속했다”고 보인다.
  • 인스턴스 메서드와 static 메서드는 모두 클래스의 정보로서 JVM의 메서드 영역에 보관된다. 즉 둘 다 클래스에 속한다고 할 수 있다.
  • 위 말의 요지는 “인스턴스 메서드는 반드시 인스턴스가 필요하지만, static 메서드는 필요하지 않다”이다.
  • 인스턴스 메서드는 실행될 때 실행의 대상이 되는 객체를 참조하기 위해 암묵적으로 this 키워드를 사용한다. 따라서 인스턴스가 없으면 안 된다.
  • static 메서드는 클래스 그 자체에 속하므로 인스턴스가 없어도 실행된다.
  • 인스턴스 메서드의 this 사용 코드 예시

      public class Calculator {
          private int value;  // Instance field
            
          // Instance method
          public void add(int number) {
              this.value += number;
          }
            
          // Static method  
          public static int multiply(int a, int b) {
              return a * b;
          }
      }
        
      // JVM이 보는 인스턴스 메서드의 모습.
      // 개발자가 명시적으로 this 파라미터를 넣지 않으면 
      // 컴파일러가 넣는다.
      public void add(Calculator this, int number) {
          this.value += number;
      }
        
      // JVM이 보는 static 메서드의 모습.
      // static 메서드는 숨겨진 this 파라미터가 없다.
      public static int multiply(int a, int b) {
          return a * b;
      }
    

코드 예시

  • 자동차 클래스

      public class Car {
          // Instance variable (each Car has its own)
          private String model;
          private int speed;
        
          // Static variable (shared by all Cars)
          private static int numberOfCars = 0;
        
          // Constructor
          public Car(String model) {
              this.model = model;
              this.speed = 0;
              numberOfCars++; // Increment the shared static variable
          }
        
          // --- INSTANCE METHODS ---
          // Actions that a specific Car can do.
        
          public void accelerate(int increment) {
              this.speed += increment; // 'this' refers to this specific object
              System.out.println(model + " is accelerating. Speed: " + speed + " mph");
          }
        
          public void displayInfo() {
              // Can access BOTH instance AND static members
              System.out.println("Model: " + this.model + ", Speed: " + speed);
              System.out.println("Total cars created: " + numberOfCars); // Accessing static variable
          }
      }
    

static 메서드

특징

  • 클래스 그 자체와 클래스의 인스턴스를 통해서 호출될 수 있다.
  • 클래스의 정적 필드에만 접근할 수 있다.
  • 인스턴스를 참조하지 않으므로 this 키워드를 사용할 수 없다.
  • 클래스가 처음으로 메모리에 로딩될 때 한 번 로딩된다.
  • 객체의 상태와 무관한 유틸리티 기능을 공유할 목적으로 정의된다.

유스 케이스

  • 유틸리티 또는 헬퍼 메서드가 필요할 때
  • 애플리케이션의 설정에 따라 인스턴스를 생성하는 팩토리 메서드를 구성할 때
  • 입력값에 따라서만 동작하는 기능성 메서드가 필요할 때

➕왜 인스턴스에 static 메서드를 호출해도 this 키워드를 사용할 수 없을까?

  • static 메서드는 기술적으로 인스턴스를 통해서도 호출될 수 있다. 그런데 왜 이런 경우에도 this 키워드를 사용할 수 없을까?
  • static 메서드는 컴파일 때 선언된 타입을 기반으로 작동한다. 즉 런타임 때 결정되는 실제 객체 타입인 인스턴스와 무관하다.
  • 따라서 인스턴스를 통해 static 메서드를 호출한다 한들 this 키워드는 사용할 수 없다.
  • 코드로 보는 예시
    • 흔히 하는 예상: static 메서드가 인스턴스(Child)를 통해 실행됐으니까, static 메서드가 Child를 참조하려고 this를 쓸 수 있지 않을까?
    • 사실: 정적 메서드인 staticMethod는 컴파일 때 처리되며, 실행될 때 선언된 타입, 즉 Parent만 필요하다. 런타임 때 사용되는 실제 타입인 Child는 전혀 고려하지 않는다. 즉 Child를 참조할 수 있는 this를 사용할 수 없다.
      Parent pa = new Child();
      pa.staticMethod();
    

➕자바에서 가장 유명한 static 메서드인 main 메서드를 알아보자

  • main 메서드의 정확한 생김새는 “public static void main(String[] args)”이다.
  • public: 메서드가 어디서든지 접근 가능하여 프로그램의 외부에 있는 JVM이 접근하도록 허용한다.
  • static: 메서드를 인스턴스가 아닌 클래스 그 자체에 속하게 만든다. 즉 인스턴스가 없어도 애플리케이션이 실행될 수 있게 만든다.
  • void: main 메서드의 목적인 애플리케이션을 실행하는 것이다. 무언가를 반환하기 위함이 아니다.
  • main: 애플리케이션을 실행하는 메서드의 이름으로, JLS에 명시되어 있다. 즉 이름을 begin, start 등으로 바꾸면 애플리케이션이 실행되지 않는다.
  • String[] args: 프로그램이 들여오는 커맨드 라인 아규먼트들이다.

코드 예시

  • 자동차 클래스

      public class Car {
          // Instance variable (each Car has its own)
          private String model;
          private int speed;
        
          // Static variable (shared by all Cars)
          private static int numberOfCars = 0;
        
          // Constructor
          public Car(String model) {
              this.model = model;
              this.speed = 0;
              numberOfCars++; // Increment the shared static variable
          }
        
          // --- STATIC METHODS ---
          // Utility functions related to Cars, but not to any single Car.
        
          public static void displayTotalCars() {
              // Can only access STATIC members
              System.out.println("Total number of cars: " + numberOfCars);
        
              // COMPILE-TIME ERROR: Cannot access instance members
              // System.out.println(model); // What model? There's no object!
              // System.out.println(this.speed); // No 'this' in a static context!
          }
        
          // A common utility static method
          public static int convertMphToKph(int mph) {
              return (int)(mph * 1.60934);
          }
      }
    

Categories:

Updated: