응용 프로그램을 설계할 때, 설계가 용이하고, 이해하기 쉽고, 단위로 디버깅이 가능하도록 코드를 작은 부분으로 나누는 것이 핵심 원칙이다.
메소드는 한국어로 번역하면 함수인데, 메소드와 함수에는 약간의 차이가 있다.
메소드는 객체의 동작을, 함수는 기능 구현(ex: static method)을 나타낸다.
메소드
메소드는 Java 프로그램에서 (하나의) 특정 작업을 수행하는 일련의 문들을 하나로 묶은 그룹이다.
문들을 하나의 그룹으로 묶을 때에는 블록 단위로 묶인다.
메소드는 함수, 서브루팅, 프로시저 등과 비슷한 개념이지만 클래스의 안에서만 존재할 수 있으며, 반드시 클래스 / 객체로부터 호출되어야만 한다.
대표적인 예시로는
- main 메소드: Java 응용 프로그램 진입점
- println 메소드: Java 라이브러리가 제공하는 표준 출력 메소드 (이것도 static임)
메소드 생성
public class MyClass {
static void myMethod(String name) {
System.out.println(“Hello ” + name);
}
public static void main(String[] args) {
System.out.println(“main method”);
}
}
위 코드와 같이
메소드 이름: myMethod
메소드 파라미터: (String) name
메소드 바디: {System.out.println("Hello " + name);}
반환(return) 타입: void
로 구성되어있다.
Java에서 메소드를 선언할 때에는 언제나 클래스 안에서만 가능하다. Java의 모든 구현은 클래스 안에 존재한다.
메소드 호출
- 같은 클래스 내에서 호출하는 경우
public class MyClass {
public static void myMethod() {
System.out.println("Hello, World");
}
public static void main(String[] args) {
System.out.println("Start");
myMethod();
System.out.println("End");
}
}
해당 함수명만 이용해서 호출하면 된다.
- 다른 클래스에서 호출하는 경우
public class MyClass {
public static void main(String[] args) {
System.out.println("Start");
OtherClass.otherMethod();
System.out.println("End");
}
}
class OtherClass {
public static void otherMethod() {
System.out.println("Hello, World");
}
}
해당 클래스를 참조하고 함수명을 이용해서 호출하면 된다.
여기서 어디에 위치한 함수를 호출한다는 의미에서 클래스(OtherClass.)를 참조하는 것이다.
해당 클래스의 메소드는 private이 아니어야 외부에서 호출이 가능하다.
- 중첩 호출하는 경우가 있다.
중첩 호출은 하나의 함수 안에서 또 다른 함수를 호출하는 것이다.
메소드로 전달되는 파라미터
파라미터는 formal parameter와 actual parameter(argument)가 있다.
public class MyClass {
static int sum(int a, int b) {
return a + b;
}
public static void main(String[] args) {
sum(95, 31);
}
}
- formal parameter (매개변수)
메소드를 정의할 때 해당 메소드에서 전달 받을 변수의 형태를 의미한다.
위 코드에서는 int a, int b에 해당하는 부분이다.
- actual parameter / argument (함수 인자)
메소드를 호출할 때 해당 메소드로 전달하는 실제 값을 의미한다.
위 코드에서 95, 31에 해당하는 부분이다.
return statement
메소드 안에서 return 문을 만나면 메소드는 뒤에 남아있는 코드는 실행하지 않는 채로 실행을 멈추고 바로 호출자 코드로 돌아간다.
메소드는 일반적으로 return 문이 없더라도 메소드의 마지막에 도달하면 호출자 코드로 돌아간다.
하지만 메소드가 void가 아닌 다른 타입으로 정의된 경우에는 컴파일 에러가 발생할 것이니 반드시 return 문을 선언하고 메소드에서 선언한 반환 타입의 값을 호출자에게 반환해야한다.
void 함수는 return이 필요없을까? 무한 루프 중에 빠져나가거나 등의 이유로 넣는다.
지역 변수 (Local Variable)
변수는 지역 변수와 전역 변수(공유 변수)로 나뉜다.
- 지역 변수 (local variable)
메소드가 시작될 때 생성
메소드(블록) 내에서만 유효함, 즉, 메소드가 종료되거나 블록을 벗어나면 제거된다.
서로 다른 블록에서의 지역 변수는 변수명이 같더라도 서로 다른 변수이며, 할당된 메모리도 다르다.
- 전역 변수 (global variable)
클래스 레벨에서 모두 공유할 수 있는 변수이다.
public class MethodCall {
static int count = 0;
static void myMethod() {
count++
}
static void myMethod2(){
int count;
}
public static void main(String[] args) {
myMethod();
myMethod();
System.out.println(count); // 2
}
}
위 코드처럼 count 변수를 클래스 내의 다른 변수들도 접근할 수 있다.
또, myMethod2() 처럼 전역 변수의 이름과 같은 변수명을 사용할 수 있다. (굳이? 라고 생각한다.)
파라미터 전달 방식
메소드로 파라미터 전달하는 방식으로는 값에 의한 전달, 참조에 의한 전달 2가지가 있다.
- 값에 의한 전달 Pass by value
값을 복사해서 전달 (따라서, 메모리 할당도 새로운 메모리를 할당 받는다)
값을 수정해도 원본 데이터에는 영향을 미치지 않음
- 참조에 의한 전달 Pass by Reference
주소 값을 전달 (실제 값이 있는 위치를 전달)
값을 수정하면 원본 데이터의 값에 영향을 미침
Java에서는 모든 파라미터 전달에 Pass by value 만을 사용한다.
(C++에서의 &, C#에서의 ref 처럼 Pass by reference 할 수 있는 방법이 아예 없음)
그래서 Java에서 swap() 정의하는 것도 다르다 ㅎㅎ (링크 참고: https://co1nam.tistory.com/21)
여기서 헷갈릴 수 있는 것은 파라미터로 배열과 같은 참조값들이 전달될 때에도 Pass by value인데, 이는 참조값을 복사해서 전달했다고 생각하면 된다.
가변 길이 파라미터
기능이 동일한 메소드를 파라미터 개수에 따라 여러개 만들기에는 코드가 너무 길어진다.
하나의 구현으로 파라미터 개수에 상관없이 동일하게 작동하도록 Java는 가변 길이 파라미터 목록을 배열로 변환하여 전달할 수 있도록 한다.
배열로 변환되어 전달되기 때문에, 전달받은 메소드에서는 해당 파라미터들을 배열처럼 활용할 수 있다. (예: values[0])
public class VariantParameters {
static int max(int... values) {
int max = Integer.MIN_VALUE;
for (int value : values) {
if (value > max)
max = value;
}
return max;
}
public static void main(String[] args) {
int maxNumber = max(9, 6, 0, 1, 5);
System.out.println("maxNumber: " + maxNumber); // 9
}
}
위 코드처럼 파라미터 타입 뒤에 ... 을 붙이면 된다.
다른 타입의 파라미터와 사용하는 경우 double avg, int... values 와 같이 목록 마지막에 선언해야 한다. (따라서, 메소드에 하나만 사용할 수 있다)
재귀 메소드, 메소드 오버로딩, 메소드 시그니처는 (2)에서...
'Java' 카테고리의 다른 글
[Java] 상속 Inheritance (0) | 2024.02.26 |
---|---|
[Java] 메소드와 파라미터 (2) - 재귀 메소드, 메소드 오버로딩, 메소드 시그니처 (0) | 2024.02.22 |
[Java] 문과 표현식 (3) (0) | 2024.02.20 |
[Java] 문과 표현식 (2) (2) | 2024.02.20 |
[Java] 문과 표현식 (1) (0) | 2024.02.20 |