Java/OOP

필드(Field)와 메서드(Method)

WY J 2022. 7. 8. 16:47

필드(Field)

  • 필드는 ‘클래스에 포함된 변수'를 의미하는 것으로 객체의 속성을 정의 한다.
  • 변수는 클래스 변수(cv, class variable), 인스턴스 변수(iv, instance variable), 지역 변수(lv, local variable)라는 세 가지로 구분 된다.
  • 이중에 필드 변수는 클래스 변수와 인스턴스 변수이다.
  • 클래스 변수와 인스턴스 변수는 다시 static 키워드의 유무로 구분할 수 있다.

 

class Example { // => 클래스 영역
	int instanceVariable; // 인스턴스 변수
	static int classVariable; // 클래스 변수(static 변수, 공유변수)

	void method() { // => 메서드 영역
		int localVariable = 0; // 지역 변수. {}블록 안에서만 유효
	}
}

 

변수의 종류?

인스턴스 변수(iv)

  • 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수로 new 생성자() 를 통해 인스턴스가 생성될 때 만들어진다.
  • 클래스를 통해 만들어진 인스턴스는 힙 메모리의 독립적인 공간에 저장되고, 동일한 클래스로부터 생성되었지만 객체의 고유한 개별성을 가진다.
  • 마치 사람마다 성별, 이름, 나이, MBTI가 다 다르듯 인스턴스 변수는 그 고유한 특성을 정의하기 위한 용도로 사용된다.

클래스 변수(cv)

  • 한 클래스로부터 생성되는 모든 인스턴스 들이 특정한 값을 공유해야하는 경우에 주로 static 키워드를 사용하여 클래스 변수를 선언.
  • 클래스 변수는 인스턴스 변수와 달리 인스턴스를 따로 생성하지 않고도 언제라도 클래스명.클래스변수명 을 통해 사용이 가능하다.
  • 예를 들면, Example.classVariable 로 클래스 변수를 사용할 수 있다.

지역 변수(lv)

  • 지역변수는 메서드 내에 선언되며 메서드 내({} 블록)에서만 사용가능한 변수이다.
  • 멤버 변수와는 다르게 지역변수는 스택 메모리에 저장되어 메서드가 종료되는 것과 동시에 함께 소멸 한다.
  • 힙 메모리에 저장되는 필드 변수는 객체가 없어지지 않는 한 절대로 삭제되는 않는 반면, 스택 메모리에 저장되는 지역변수는 한동안 사용되지 않는 경우 가상 머신에 의해 자동으로 삭제된다.

 

 

필드 변수와 지역 변수의 차이점

직접 초기화하지 않으면 값을 출력할 때에 오류가 발생하는 지역변수와는 다르게 필드 변수는 직접적으로 초기화를 실행하지 않더라도 강제로 초기화가 이뤄진다. 이것 또한 메모리의 저장 위치와 연관성을 가진다. 힙 메모리에는 빈 공간이 저장될 수 없기 때문에 이곳에 저장되는 필드는 강제로 초기화되지만, 스택 메모리는 강제로 초기화되지 않으므로 지역 변수는 선언시 반드시 초기화를 실행해주어야 한다.

 

static 키워드 : 객체 간 공유 변수, static 영역에 저장

  • 클래스 변수와 인스턴스 변수를 구분하기 위한 방법 중 하나이고, ‘정적 멤버(static member)’ 이라 부른다.
  • static은 클래스의 멤버(필드, 메서드, 이너 클래스)에 사용하는 키워드
  • 이 둘을 구분하는 차이는 인스턴스 멤버는 객체를 생성한 이후에 변수와 메서드에 접근하여 해당 멤버를 사용가능한 반면, static 클래스 멤버는 인스턴스의 생성 없이도 클래스명.멤버명 만으로도 사용이 가능하다.
  • static 클래스 멤버는 new 키워드로 생성된 인스턴스와 같이 힙 메모리에 생성되는게 아닌, 클래스 내부에 저장 공간을 가지고 있기 때문에 객체 생성 없이 곧바로 사용할 수 있다.

 

확인하는 코드

public class StaticTest {
    public static void main(String[] args) {
        StaticExample staticExample = new StaticExample(); // 객체 생성
        System.out.println("인스턴스 변수: " + staticExample.num1); // static 키워드가 없는 인스턴스 변수
        System.out.println("클래스 변수: " + StaticExample.num2); //static 키워드가 있는 클래스 변수
    }
}

class StaticExample {
    int num1 = 10;         // 참조변수 num1은 인스턴스 변수
    static int num2 = -10; // 참조변수 num2은 static 키워드 붙임
}

//Output
인스턴스 변수: 10
클래스 변수: -10

정적 필드는 객체 간 공유 변수의 성질이 있다는 점이 메서드에도 동일하게 적용된다.

일반적인 메서드 앞에 static 키워드를 사용하면 해당 메서드는 정적 메서드가 된다.

정적 메서드도 정적 필드와 마찬가지로 클래스명만으로 바로 접근이 가능하다.

또한 정적 메서드의 경우 인스턴스 변수 또는 인스턴스 메서드를 사용할 수 없다.

이유는, 정적 메서드는 인스턴스 생성 없이 호출이 가능하기 때문에 정적 메서드가 호출되었을 때 인스턴스가 존재하지 않을 수 있기 때문이다.

 

정적 필드 간에 값 공유 확인

public class StaticFieldTest {
    public static void main(String[] args) {
        StaticField staticField1 = new StaticField(); // 객체 생성
        StaticField staticField2 = new StaticField(); // 객체 생성

        staticField1.num1 = 100;   // 인스턴스 값 100 입력
        staticField2.num1 = 1000;  // 인스턴스 값 1000 입력

        System.out.println(staticField1.num1); // 인스턴스 값 100 출력
        System.out.println(staticField2.num1); // 인스턴스 값 1000 출력

        staticField1.num2 = 150;   // 정적 값 150 공유 선언
        staticField2.num2 = 1500;  // 정적 값 1500 공유 선언
        System.out.println(staticField1.num2); // 정적 값 1500 출력
        System.out.println(staticField2.num2); // 정적 값 1500 출력

    }
}

class StaticField {
    int num1 = 10;         // 인스턴스 필드 선언
    static int num2 = 15;  // 정적 필드 선언
}

//출력값
100    // 고유성을 가진 인스턴스 값 출력
1000   // 고유성을 가진 인스턴스 값 출력
1500   // 값이 공유된 정적 값 출력
1500   // 값이 공유된 정적 값 출력

 


메서드(Method)

  • 객체 지향 프로그래밍에서 클래스 내부에 정의된 함수를 말한다. (멤버 함수 라고도 한다.)
  • 메서드의 시그니처 는 해당 메서드가 어떤 타입을 반환하는 가(반환 타입), 메서드 이름이 무엇(메서드명)이며 해당 작업을 수행하기 위해서 어떤 재료들이 필요한지(매개 변수)에 대한 정보를 포함한다.
  • 메서드의 바디는 괄호({}) 안에 해당 메서드가 호출되었을 때 수행되어야하는 일련의 작업들을 표시한다.
  • 메서드의 반환타입이 void가 아닌 경우에는 메서드 바디({} )안에 반드시 return 문이 존재해야 한다.
  • 결과값은 반드시 반환타입과 일치하거나 적어도 자동 형변환이 가능한 것이어야 한다.

 

자바제어자 반환타입 메서드명(매개 변수) { // 메서드 시그니처
	메서드 내용 // 메서드 바디
}

public static int add(int x, int y) { // 메서드 시그니처
	int result = x + y; // 메서드 바디
	return result;
}

void printHello() { // 반환타입이 void인 메서드
	System.out.println("hello!");
} // 호출되면 hello! 출력

int getNumSeven() { // 매개변수가 없는 메서드
	return 7;
} // 호출되면 7 반환

Double multiply(int x, double y) { // 매개변수가 있는 메서드
	double result = x * y;
	return result;
} // int와 double형을 산술 연산하면 범위가 더 큰 타입으로 자동으로 형 변환

 

메서드의 호출

객체참조변수이름.메서드이름(); // 클래스 외부에서 호출 방법
객체참조변수이름.메서드이름(인수1, 인수2) // 클래스 외부에서 호출 방법

메서드이름(매개변수1, 매개변수2, ...); // 클래스 내부에서 호출방법. 매개 변수가 없을 수도 있음.

void printHello(); // 위의 코드 예제 호출
int getNumSeven();
Double multiply(4, 4.0);

//출력값
hello!
7
16.0
  • 클래스 외부에서 메서드를 사용하기 위해서는 먼저 인스턴스를 생성한 후에 포인트 연산자(.)를 통해 메서드를 호출할 수 있다.
  • 클래스 내부에 있는 메서드끼리는 따로 객체를 생성하지 않고도 서로를 호출할 수 있다.
  • 메서드 호출 시 괄호() 안에 넣어주는 입력 값을 ‘인자(argument)’라고 하는데, 인자의 개수와 순서는 반드시 메서드를 정의할 때 선언된 매개변수와 일치해야 한다.

 

 

 

클래스 메서드

  • 클래스 메소드는 객체를 생성하지 않고 호출이 가능하다. 
  • 클래스 메소드는 인스턴스를 생성하지 않고 바로 사용할 수 있으며 메소드 내부에서 인스턴스 변수를 사용할 수 없다.

인스턴스 메서드 

  • 인스턴스 메소드는 메소드의 작업 수행 시 인스턴스 변수가 필요한 메소드이다. 
  • 인스턴스 변수는 객체를 생성해야 만들어지기 때문에 인스턴스 메소드가 인스턴스를 생성해야만 호출할 수 있다.
void on() {  } //인스턴스 메소드
static void off() {  } //클래스 메소드

 

 

 

추가 참고 내용

 

입력값과 리턴값에 따른 종류

  • 입력과 출력이 모두 있는 메소드의 작성 : 변수 = 객체.메소드명(매개변수);
  • 입력과 출력이 모두 없는 메소드의 작성 : 객체.메소드명();
  • 입력은 없고 출력은 있는 메소드의 작성 : 변수 = 객체.메소드명();
  • 입력은 있고 출력은 없는 메소드의 작성 : 객체.메소드명(매개변수);

 

메서드 오버로딩(Method Overloading)

  • 하나의 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것을 의미한다.
  • 하나의 메서드로 여러 경우의 수를 해결할 수 있다.
  • 반환 타입은 오버로딩이 성립하는 데에 영향을 주지 못한다.

 

메서드를 오버로딩하려면?

  1. 메서드의 이름이 같아야 한다.
  2. 매개변수의 개수 또는 타입이 달라야 한다.