[JAVA 기초]
2. 필드(Field)와 메서드(method)
개요
클래스는 크게 네 가지 요소로 구성되어 있습니다.
각각 필드(field), 메서드(method), 생성자(constructor), 그리고 이너 클래스(inner class)입니다.
그중 필드와 메서드는 각각의 클래스가 가지는 속성(state)과 기능(behavior)을 대표합니다. 일반적으로 하나의 객체는
다양한 속성과 기능의 집합으로 이뤄져 있습니다. 그리고 이러한 속성과 기능은 이너클래스와 함께 객체의
멤버(member)라 부릅니다.
이번 글을 통해 필드와 메서드에 대해 공부해 봅니다.
학습 목표
- 객체의 속성을 정의하는 필드를 이해합니다.
- 세 가지 종류의 변수를 구분합니다.
- 각각의 변수가 저장되는 위치를 이해합니다.
- static 키워드가 무엇이며, 언제 사용되는지 이해합니다.
- 객체의 기능을 정의하는 메서드를 이해하고, 메서드의 구성요소와 호출에 대해 이해합니다.
- 메서드 오버로딩을 이해하고 그 장점을 이해합니다.
필드
필드는 '클래스에 포함된 변수'를 의미하며, 객체의 속성(state)을 정의할 때 사용됩니다.
JAVA에서 변수는 크게 3가지로 구분됩니다.
- 클래스 변수(cv, class variable)
- 인스턴스 변수(iv, instance variable)
- 지역 변수(lv, local variable)
이 중 필드는 클래스 변수와 인스턴스 변수이며, 이는 static 키워드의 유무로 확인할 수 있습니다.
static 키워드가 함께 선언된 것은 클래스 변수, 그렇지 않은 것은 인스턴스 변수이며, 이 두 가지 변수 유형에 포함되지 않고 메서드 내에 포함된 모든 변수를 지역 변수라 부릅니다.
위 세 가지의 변수는 선언된 위치에 따라 그 종류가 결정되며 각각 다른 유효 범위(scope)를 가지게 됩니다. 아래의 예시 코드를 보겠습니다.
class Example { // => class
int instanceVariable; // instanceVariable
static int classVariable; // classVariable(static variable)
void method() { // => method
int localVariable = 0; // local variable
}
}
위의 Example 클래스 안에 세 가지 유형의 변수를 선언하였습니다.
먼저 인스턴스 변수는 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수로써
인스턴스가 생성될 때 정의합니다. 클래스를 통해 만들어진 인스턴스는 힙 메모리(heap memory)의 독립적인 공간에 저장되며, 동일한 클래스로 생성되었지만 객체마다 고유한 개별성을 가집니다.
다음으로, static 키워드를 통해 선언하는 클래스 변수는 독립적인 저장 공간을 가지는 인스턴스 변수와 다르게 공통된 저장 공간을 공유합니다.
즉, 한 클래스로부터 생성되는 모든 인스턴스들이 특정한 값을 공유할 때 static 키워드를 사용하여 클래스 변수로 선언하게 됩니다. 또한, 클래스 변수는 인스턴스 변수와는 달리 인스턴스를 따로 생성하지 않고도 언제라도 class.feild를 사용해 사용이 가능합니다. 위의 코드로 예를 들면 Example.classVariable 명령어를 통해 클래스 변수를 사용할 수 있습니다.
마지막으로 지역변수는 메서드 내에 선언되며 메서드 내 ({} 블록)에서만 사용 가능한 변수입니다.
멤버 변수와는 다르게 지역변수는 스택 메모리에 저장되어 메서드가 종료되는 것과 함께 소멸되어 더 이상 사용할 수 없게 됩니다.
또한 힙 메모리에 저장되는 인스턴스 변수와 클래스 변수와는 다르게 스택 메모리에 저장되는 지역 변수는 한동안 사용되지 않는 경우 가상 머신에 의해 자동으로 삭제됩니다.
마지막으로 인스턴스 변수, 클래스 변수와 지역변수의 차이점은 초기값에 있습니다.
직접 초기화하지 않으면 오류가 발생하는 지역변수와는 다르게 필드 인스턴스, 클래스 변수는 직접적으로 초기화를 실행하지 않더라도 강제로 초기화가 이뤄집니다.
이 이유는 메모리의 저장 위치와 연관이 있습니다. 힙 메모리에는 빈 공간이 저장될 수 없기 때문에 이곳에 저장되는 필드는 강제로 초기화되지만, 스택 메모리는 강제로 초기화되지 않으므로 지역 변수는 반드시 초기화를 실행해주어야 합니다.
Static 키워드
static은 클래스의 멤버(필드, 메서드, 이너 클래스)에 사용하는 키워드입니다.
static 키워드가 붙어있는 멤버를 '정적 멤버(static member)'라 부릅니다.
코드를 통해 우리가 배운 내용을 확인해 봅니다.
public class StaticTest {
public static void main(String[] arg) {
StaticField staticField1 = new StaticField(); // staticField1 객체 생성
StaticField staticField2 = new StaticField(); // staticField2 객체 생성
staticField1.number1 = 100; // staticField1의 number1 변수의 리터럴을 10으로 저장
staticField2.number1 = 1000; // staticField2의 number1 변수의 리터럴을 1000으로 저장
System.out.println(staticField1.number1); // 100 출력
System.out.println(staticField2.number1); // 1000 출력
staticField1.number2 = 150; // staticField1의 number2 변수의 리터럴을 150으로 저장
staticField2.number2 = 1500; // staticField2의 number2 변수의 리터럴을 1500으로 저장
System.out.println(staticField1.number2); // 1500 출력
System.out.println(staticField2.number2); // 1500 출력
}
}
class StaticField {
int number1 = 10; // 인스턴스 변수 선언
static int number2 = 15; // 클래스 변수 선언
}
//출력값
100
1000
1500
1500
위의 예시를 보면 static 키워드의 유무에 따라 달라지는 차이를 명확하게 확인해 볼 수 있습니다.
static 키워드를 사용한 number2 변수의 값이 모든 인스턴스에 공유됨을 확인할 수 있었습니다.
메서드
메서드는 "특정 작업을 수행하는 일련의 명령문들의 집합"을 의미하며, 클래스의 기능을 담당합니다.
메서드는 머리에 해당하는 메서드 시그니쳐(method signature)와 몸통에 해당하는 메서드 바디(method body)로 구분할 수 있습니다.
public static int add(int x, int y) { // method signature
int result = x + y; // method body
return result;
}
=
접근제어자 자바제어자 반환타입 메서드명(매개 변수) { // method signature
메서드 내용 // method body
}
위의 예제는 메서드의 시그니처와 바디가 각각 어떻게 구성되어 있는지를 보여주고 있습니다.
위의 코드는 메서드명이 add인 메서드이며, int 타입 2개의 값(x, y)을 받아 더한 뒤 int 타입의 결괏값을 반환하는
메서드라 정리할 수 있습니다.
만약 메서드의 반환타입이 void가 아닌 경우 메서드 바디안에는 반드시 return 문이 존재해야 합니다.
return문은 작업을 수행한 결과값을 호출한 메서드로 전달합니다. 여기서 결과 값은 반드시 반환타입과 일치하거나
적어도 자동 형변환이 가능한 것이어야 합니다.
메서드의 호출
메서드도 클래스의 멤버이므로 클래스 외부에서 메서드를 사용하기 위해서는 먼저 인스턴스를 생성하여야 합니다.
인스턴스를 생성한 후 포인트 연산자(.)를 통해 메서드를 호출할 수 있습니다.
만약 클래스 내부에 있는 메서드끼리는 따로 객체를 생성하지 않고도 서로를 호출할 수 있습니다.
메서드의 호출은 다음과 같이 할 수 있습니다.
public class Main {
public static void main(String[] args) {
MethodExample Example = new MethodExample(); //인스턴스 생성
Example.printHello(); //printHello() 메서드 호출
System.outprintln(Example.getNumberSeven()); //getNumberSeven 메서드 호출
System.outprintln(Example.multiple(4,4.0)); //multiply 메서드 호출
}
}
class MethodExample{
void printHello(){ // 반환타입이 void인 메서드
System.out.println("Hello");
}
int getNumberSeven(){ // 매개변수가 없는 메서드
return 7;
}
Double multiply(int x, double y){ //매개변수가 있는 메서드
double result = x * y;
return result;
}
}
//출력값
hello!
7
16.0
위의 코드 예제를 통해 각각 리턴 타입에 맞는 결괏값을 바르게 반환하는지 확인할 수 있습니다.
메서드 호출 시 괄호() 안에 넣어주는 입력 값을 우리는 '인자(argument)'라고 하는데, 인자의 개수와 순서는 반드시
메서드를 정의할 때 선언된 매개변수와 일치하여야 합니다. 그렇지 않은 경우 실행 에러가 발생하며, 인자의
타입 또한 매개변수의 그것과 일치하거나 자동 형변환이 가능한 것이어야 합니다.
메서드 오버로딩
메서드 오버로딩이란 하나의 클래스 안에 같은 이름의 메서드를 여러 개 정의하는 것을 의미합니다.
메서드 오버로딩을 제대로 이해하기 위해서는 메서드 시그니쳐(method signature)에 대한
개념 이해가 먼저 선행되어야 합니다.
이것은 메서드의 이름 또는 매개변수의 타입이 다르면 다른 메서드라고 인식하는 자바 가상 머신(Java Virtual machine)의
기능과 관계가 있습니다.
메서드 오버로딩은 다음과 같이 할 수 있습니다.
public class Overloading {
public static void main(String[] args) {
Shape result = new Shape(); //객체 생성
result.area(); //메서드 호출
result.area(5);
result.area(10, 10);
result.area(6.0, 12.0);
}
}
class Shape {
public void area(){
System.out.println("넓이");
}
public void area(int r){
System.out.println("원 넓이 = " + 3.14 * r * r);
}
public void area(int w, int l) {
System.out.println("직사각형 넓이 = " + w * 1);
}
public void area(double b, double h){
System.out.println("삼각형 넓이 = " + 0.5 * b * h);
}
}
//출력값
넓이
원 넓이 = 78.5
직사각형 넓이 = 100
삼각형 넓이 = 36.0
위의 예시를 보면, Shape 클래스 안의 메서드들이 모두 area()라는 메서드 명을 가지고 있음에도 각기 다른 출력값을 반환하는 것을 확인할 수 있습니다.
오버로딩이 성립하기 위해서는 크게 두 가지 조건이 성립되어야 합니다.
- 같은 이름의 메서드명을 써 주어야 한다.
- 매개변수의 개수나 타입이 다르게 정의되어야 한다.
만약 위 조건이 하나라도 충족되지 않는다면 중복 정의로 간주되어 컴파일 에러가 발생하게 됩니다.
그렇다면 오버로딩의 장점은 무엇일까요?
가장 큰 장점은 '하나의 메서드로 여러 경우의 수를 해결할 수 있다'입니다.
이번글을 통해 필드와 메서드에 대해 알아보았습니다.
다음에는 클래스의 네 가지 요소 중 생성자에 대해 알아보도록 하겠습니다.
'JAVA > JAVA 이론' 카테고리의 다른 글
[JAVA 이론] 캡슐화(encapsulation) (0) | 2023.02.28 |
---|---|
[JAVA 이론] 상속(inheritance) (0) | 2023.02.27 |
[JAVA 이론] 내부 클래스(Inner Class) (0) | 2023.02.26 |
[JAVA 이론] 생성자(Constructor) (0) | 2023.02.25 |
[Java 이론] 클래스와 객체 (0) | 2023.02.23 |