필드(Field)란?
필드란 클래스에 포함된 변수를 의미하는 것으로 객체의 속성을 정의할 때 사용된다. 자바에서 변수는 크게 클래스 변수(cv, class variable), 인스턴스 변수(iv, instance variable), 지역 변수(lv, local variable) 가 있다. 이 중 우리가 필드라 부른 것은 클래스 변수와 인스턴스 변수이며 이 둘은 다시 static 키워드의 유무로 구분할 수 있다.
static 키워드와 함께 선언된 것이 클래스 변수, 그렇지 않은 것은 인스턴스 변수이다. 그리고 이 두 가지의 변수 유형에 포함되지 않고 메서드 내에 포함되는 모든 변수를 지역변수 라고 한다.
class Example { // => 클래스 영역
int instanceVariable; // 인스턴스 변수
static int classVariable; // 클래스 변수(static 변수, 공유변수)
void method() { // => 메서드 영역
int localVariable = 0; // 지역 변수. {}블록 안에서만 유효
}
}
인스턴스 변수(iv, instance variable)
인스턴스 변수는 인스턴스가 가지는 각각의 고유한 속성을 저장하기 위한 변수로 new 생성자를 통해 인스턴스가 생성될 때 만들어진다. 클래스를 통해 만들어지는 인스턴스는 힙 메모리의 독립적인 공간에 저장되고, 동일한 클래스로부터 생성되었지만 객체의 고유한 개별성을 가진다.
클래스 변수(cv, class variable)
클래스 변수는 static 키워드를 통해 선언하는데 독립적인 저장공간을 가지는 인스턴스 변수와 다르게 공통된 저장공간을 공유한다. 한 클래스로부터 생성되는 모든 인스턴스가 특정한 값을 공유해야 할 때는 주로 static 키워드를 사용하여 클래스 변수를 선언한다. 또한 클래스 변수는 인스턴스 변수와 다르게 인스턴스를 따로 생성하지 않고도 클래스명.클래스변수명 을 통해 사용이 가능하다.
지역 변수(lv, local variable)
지역변수는 매서드 내에 선언되며 메서드 내 { } 안에서만 사용이 가능하다. 멤버 변수와는 다르게 지역변수는 스택 메모리에 저장 되어있다가 메서드가 종료되는 순간 함께 소멸되어 더 이상 사용할 수 없게 된다.
Static
Static 은 클래스의 멤버(필드, 메서드, 이너클래스)에 사용하는 키워드이다. Static가 붙어있는 멤버를 정적 멤버(static member)라고 부른다. Static 키워드 유무에 따른 차이를 확인해보자.
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;
static int num2 = -10;
}
//출력값
인스턴스 변수: 10
클래스 변수: -10
위의 코드는 StaticExample 클래스에 static 키워드가 없는 변수 num1과 static 키워드가 있는 변수 num2에 각각 10과 -10을 할당했다. 그리고 StaticTest 클래스에서 각각의 필드값을 호출하였다. 인스턴스 변수 num1은 객체 생성 후에 포인트 연산자를 사용하여 값을 불러왔고, 클래스 변수는 객체 생성 없이 클래스 명을 사용하여 값을 불러온다. 아래 코드로 차이를 더 자세히 봐보자
public class StaticFieldTest {
public static void main(String[] args) {
StaticField staticField1 = new StaticField(); // 객체 생성
StaticField staticField2 = new StaticField();
staticField1.num1 = 100;
staticField2.num1 = 1000;
System.out.println(staticField1.num1);
System.out.println(staticField2.num1);
staticField1.num2 = 150;
staticField2.num2 = 1500;
System.out.println(staticField1.num2);
System.out.println(staticField2.num2);
}
}
class StaticField {
int num1 = 10;
static int num2 = 15;
}
//출력값
100
1000
1500
1500
StaticField 클래스 안에 인스턴스 필드(num1)와 정적 필드(num2)를 각각 선언하였고 대조를 위해 staticField1 과 staticField2 객체를 생성하였다. num1의 경우 각각의 변수가 고유성을 가지기 때문에 100, 1000이 출력되는 반면 클래스 변수인 num2는 값이 반복되어 1500이 출력 된다. 이처럼 static 키워드를 사용하면 모든 인스턴스에 적용되는 값을 공유할 수 있다.
메서드(Method)
메서드는 특정 작업을 수행하는 일련의 명령문들의 집합을 의미하며 앞서 본 것처럼 클래스의 기능에 해당하는 내용들을 담당한다. 메서드는 메서드 시그니쳐(method signature)와 메서드 바디(method body)로 구분할 수 있다. 메서드의 구성은 아래와 같다.
자바제어자 반환타입 메서드명(매개 변수) { // 메서드 시그니처
메서드 내용 // 메서드 바디
}
메서드의 시그니처는 해당 메서드가 어떤 타입을 반환하는가(반환 타입), 메서드 이름이 무엇(메서드명)이며 해당 작업을 수행하기 위해서 어떤 재료들이 필요한지(매개 변수)에 대한 정보를 포함하고 있다. 메서드명은 관례적으로 소문자로 표시 한다고 한다.
public static int add(int x, int y) { // 메서드 시그니처
int result = x + y; // 메서드 바디
return result;
}
위의 코드는 메서드 명이 add인 메서드이며 int type의 2개의 값 x, y를 받아 더한 다음 int타입의 결과값을 반환하는 메서드라 정리할 수 있겠다. 만약 메서드 반환타입이 void가 아닌 경우에는 메서드 바디({}) 안에 반드시 return 문이 존재해야 한다. 리턴문은 작업을 수행한 결과값을 호출한 메서드로 전달한다. 여기서 결과값은 반드시 반환타입과 일치하거나 적어도 자동 형변환이 가능한 것이어야 한다.
void printHello() { // 반환타입이 void인 메서드
System.out.println("hello!");
}
위의 코드의 pirntHello 메서드는 반환타입이 void, 즉 반환 값이 없는 메서드를 의미한다. 따라서 printHello 메서드는 호출되면 그저 hello! 라는 내용을 출력하고 종료된다.
int getNumSeven() { // 매개변수가 없는 메서드
return 7;
}
위의 코드의 getNumSeven 메서드는 int 타입의 결과값을 반환하는 매개변수가 없는 메서드이다. 해당 메서드가 호출되면 그냥 숫자 7을 반환하기 때문에 따로 매개변수가 필요하지 않다.
Double multiply(int x, double y) { // 매개변수가 있는 메서드
double result = x * y;
return result;
}
위의 코드의 multiply 메서드는 매개변수 x와 y를 전달받아 변환타입이 double인 result를 반환하는 매개변수가 있는 메서드이다.
메서드의 호출
메서드를 아무리 잘 정의하더라도 호출이 되지 않으면 아무 일이 일어나지 않는다. 메서드도 클래스의 멤버이므로 클래스 외부에서 메서드를 사용하기 위해서는 먼저 인스턴스를 생성해야한다. 인스턴스를 생성한 후 앞어 보았던 것처럼 포인트 연산자(.)를 통해 메서드를 호출할 수 있다. 반면 클래스 내부에 있는 메서드끼리는 따로 객체를 생성하지 않고도 서로를 호출할 수 있다.
메서드이름(매개변수1, 매개변수2, ...); // 메서드 호출방법. 매개 변수가 없을 수도 있음.
printHello(); // 위의 코드 예제 호출
getNumSeven();
multiply(4, 4.0);
//출력값
hello!
7
16.0
위의 코드는 메서드를 호출하는 기본적인 방법이다.
메서드 호출 시 괄호()안에 넣어주는 입력값을 인자(argument)라고 하는데 인자의 개수와 순서는 반드시 메서드를 정의할 때 선언된 매개변수와 일치되어야 한다. 그렇지 않은 경우 실행 에러가 발생한다. 인자의 타입 또한 매개변수의 그것과 일치하거나 자동 형변환이 가능한 것이어야 한다.
메서드 오버로딩(Method Overloading)
메서드 오버로딩이란 하나의 클래스 안에 같은 이름의 메서드를 여러개 정의하는 것을 의미한다. 보통 하나의 메서드에 하나의 기능만 구현해야 하는데 같은 이름의 메서드가 여러 기능을 구현하기 때문에 오버로딩이란 용어를 사용한다. 메서드 오버로딩을 제대로 이해하기 위해서는 먼저 메서드 시그니처(method signature)에 대한 개념 이해가 먼저 선행되어야 한다. 앞서 봤듯이 메서드 시그니처는 메서드명과 매개변수 타입을 의미하는데 각 메서드를 구분하는 용도로 사용된다. 아래의 코드로 살펴보자.
public class Overloading {
public static void main(String[] args) {
Shape s = new Shape(); // 객체 생성
s.area(); // 메서드 호출
s.area(5);
s.area(10,10);
s.area(6.0, 12.0);
}
}
class Shape {
public void area() { // 메서드 오버로딩. 같은 이름의 메서드 4개.
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 * l);
}
public void area(double b, double h) {
System.out.println("삼각형 넓이 = " + 0.5 * b * h);
}
}
//출력값
넓이
원 넓이 = 78.5
직사각형 넓이 = 100
삼각형 넓이 = 36.0
위의 예시에서 Shape 클래스 안에 있는 모든 메서드들이 area()라는 메서드 명을 가지고 있음에도 다른 출력값을 리턴한다. 오버로딩이 성립하기 위해서는 크게 두가지 조건이 성립 되어야 한다.
- 같은 이름의 메서드명을 사용해야 한다.
- 매개변수의 개수나 타입이 다르게 정의되어야 한다.
오버로딩의 장점
오버로딩의 장점은 하나의 메서드로 여러 경우의 수를 해결할 수 있다는 것이 가장 크다. 오버로딩이 지원되지 않았다면, 하나하나 일일이 메서드를 정의해줘야하는 번거로움이 발생했을 것이며 오버로딩을 통해서 같은 기능을 하는 메서드의 이름을 반복적으로 지어주지 않아도 되며, 이름만 보고도 기능을 쉽게 예측할 수 있다.
'공부 > 전자컴퓨터공학' 카테고리의 다른 글
Java 내부클래스 (Inner Class) Java 기초 배우기 (0) | 2024.05.27 |
---|---|
생성자(Constructor)란? 자바 기초 배우기 (0) | 2024.05.26 |
Java 클래스(Class) & 객체(Object) 자바 기초 배우 (0) | 2024.05.23 |
Java 배열(Array) 자바 기초 배우기 (0) | 2024.05.22 |
Java 제어문(Control Flow Statements) 조건문과 반복문 (2) | 2024.05.22 |