메소드란?
문장들을 묶어놓은것
장점
1. 코드의 중복을 줄일수 있다.
2. 코드의 관리가 쉽다.
3. 코드를 재사용할 수 있다.
4. 간결해서 이해하기 쉬워진다.
1. 중복된 코드의 간결화
작업단위로 문장들을 묶어서 이름을 붙여 사용한다. ( 중복 코드제거, 관리 용이, 재사용가능 )
public static void main(String[] args) {
...
for( int i = 0; i < 10; i++ ) {
numArr[i] = (int)(Math.random() * 10);
}
for(int i = 0; i < 10; i++) {
System.out.printf("%d", numArr[i]);
}
System.out.println();
for(int i = 0; i < 10; i++) {
System.out.printf("%d", numArr[i])
}
System.out.println();
현재 똑같은 역할을 하는 코드가 두개가 있다.
이는 코드의 중복이 되는것이고 우리가 피해야하는 코드이다
이때 사용하는것이 바로 메소드이다.
static void printArr(int[] numArr) {
for(int i = 0; i < 10; i++) {
System.out.printf("%d", numArr[i]);
}
System.out.println();
}
이런식으로 메소드를 만들고
main에서
public static void main(String[] args) {
...
for(int i = 0; i < 10; i++) {
numArr[i] = (int)(Math.random() * 10);
}
printArr(numArr)
}
이런식으로 훨씬 간결하고 읽기쉽게 사용하기 쉽게 사용할수 있다
2. 값을 입력받아 처리하고, 결과 또한 반환받을수 있다.
int add (int x, int y) {
int result = x + y;
return result;
}
- 메소드의 반환타입을 지정한다.(int)
- 메소드의 이름을 지정하고
- 입력받을 매개변수를 선언해준다.
- 그후 return 값으로 결과를 반환받는것이다. 이때 반환값은 꼭 int값이여야만 한다.
※ 클래스 = 함수 라고 많이 하지만 여기서 아주 사알짝 다른점이 있다. 이후에 재귀 함수에서 함수를 만날수 있기때문에 조금 말하자면 두가지의 차이점은 "메소드는 반드시 클래스 안에 작성되어야한다"하지만 "함수는 독립적인 존재"이다.
tip! 메서드 작성 팁
- 반복적으로 수행되는 여러 문장을 메소드로 작성한다.
- 하나의 메소드는 한가지의 기능만을 수행할 수 있도록 작성해야한다.
메소드의 구성
메소드는 선언부와 구현부로 이루어져있다.
반환타입 메소드이름(타입 변수명1, 타입 변수명2, ...)
int add ( int a, int b, ...) == 선언부
{
메소드 호출시 수행될 코드
int result = a + b; == 구현부
return result;
}
- 변수의 갯수는 0 ~ n개까지 만들수 있다 하지만 출력값은 0 ~ 1개까지 가능하다.
- 만약 출력값이 많아지면 어떻게 해야할까? : 배열이나 하나의 객체로 묶어서 반환하면 된다.
- 만약 반환 타입이 없다면 어떻게 해야할까? : 메소드 반환 타입을 void로 지정하면 된다.
- 우리가 변수를 표현할때 메소드 안에 있는 변수를 IV(지역변수)로 나타낸다고 했다.
- 메서드안에 구성된 모든 변수(int a, int b, result)는 모두 지역변수로 메소드가 사라짐과 동시에 없어진다.
- 그래서 메소드가 다르다면 변수 이름이 같아도 전혀 상관없다.
메소드의 호출
메소드이름(값1, 값2, ....) 이것이 메소드를 호출하는 방법이다.
작업에 필요한 값이 없는 메소드일 경우
print99danAll(); // 해당 메소드의 값은 지정되어있지 않다 즉 반환타입이 void이다.
작업에 필요한 값이 있는 메소드일 경우
int result = add (3,5) // 해당 메소드는 반환 타입이 int이고 값이 2개가 필요하다
add메소드를 호출하고 결과를 result에 저장하겠다 라는 말이다.
※ tip. add 에 해당하는 값은 인자(Arguments)라고 하고 인자를 받은 메소드의 값들을 전달받은 중간 매개체 라고 하여 매개변수(parameter)라고 한다.
메소드의 실행흐름
MyMath mm = new MyMath();
long value = mm.add(1L,2L);
long add(long a, long b) {
long result = a + b;
return result;
}
- 가장 먼저 인스턴스를 생성한다.
- 내가 원하는 메서드를 호출한다
- 인수 1과 2가 add 라는 메소드에 매개변수로서 대입된다
- 그리고 메소드 안의 문장이 수행되고 result를 저장하고, return문을 만나 호출한 메소들로 넘어간다.
- 그리고 호출한 곳에 결과값이 전달되고 변수를 지정해 두었다면 그곳에 결과값이 저장된다.
실행흐름은 굉장히 간단해보이지만 다양하게 읽어보아야한다.
아까부터 계속 return이 나오는데 이게 생각보다 중요하다
사람들이 많이 놓치고 지나갈수 있는 return문에 대해 배워보자
return도 꼭 이해하고 가야하는데 설렁설렁 넘어가면 나중에 꽤 큰 곤욕을 치룰수 있으니 배웠으면 좋겠다
return문
실행 중인 메소드를 종료하고 호출한 곳으로 되돌아간다.
void printGugudan(int dan) {
if(!(2 <= dan && dan <= 9) {
return;
}
for(int i = 1; i <= 9; i++) {
System.out.printf("%d * %d = %d%n", dan, i, dan * i);
}
// return;
}
자 이건 위에서 봤던 구구단 메소드이다. 보면 return 을 생략해놓았는데 중요하다면서 왜 갑자기 생략했을까?
이는 void에서만 가능한 return문의 조건인데 아까 void가 타입을 딱히 지정하지 않는다는것이라는 뜻이였다.
즉, 반환 값이 딱히 지정되어있지 않다면 그냥 return을 생략해주어도 된다는 것이다.
그렇다면 반환 타입을 지정한다면 꼭 return문을 사용해야 한다는 것일까? 맞다 ㅎ
int multiply(int x, int y) {
int result = x * y;
return result;
}
반환 타입이 int인 multiply는 return값을 정해주어야한다.
물론 당연히 int값이여야만 한다.
int max(int a, int b) {
if( a < b ) {
return b;
}
}
여기에 문제가 있다. return 이 if문 안에만 존재한다.
그럼 메소드 자체의 return문이 아닌 if문이 참일때만 return문이있기때문에 오류가 생긴다.
그래서 return 문을 또다시 작성해주어야한다.
※ tip. 수많은 return이 있고 return값을 받는 곳까지도 모든 곳의 타입은 일치해야한다.
Static 메소드와 인스턴스 메소드
- 인스턴스 메소드
- 인스턴스 생성후, '참조변수.메소드이름()' 으로 호출
- 인스턴스 멤버(iv, im)와 관련된 작업을 하는 메소드
- 메소드 내에서 인스턴스 변수(iv) 사용 가능
- static 메소드(클래스 메소드)
- 객체 생성 없이 '클래스이름.메소드이름()' 으로 호출
EX) Math.random() = random이 Math클래스의 static 메소드라서 그냥 부를수 있다 - 인스턴스 멤버(iv, im)와 관련없는 작업을 하는 메소드
- 메소드 내에서 인스턴스 변수(iv) 사용 불가
- 객체 생성 없이 '클래스이름.메소드이름()' 으로 호출
예시
class MyMath2 {
long a, b; // iv이다. 클래스 전체에서 사용할 수 있다.
long add() {
return a + b; // iv이다.
}
static long add(long a, long b) { // lv 지역변수. 메소드 내에서만 사용 가능
return a + b; // lv이다.
}
}
사용법
class MyMathTest2 {
public static void main(String[] args) {
System.out.println(MyMath2.add(200L, 100L); // MyMath클래스의 static메소드를 바로 사용한다.
MyMath2 mm = new MyMath2(); // 인스턴스를 생성해야만
mm.a = 200L;
mm.b = 100L; // 각각의 변수의 수를 지정하고
System.out.println(mm.add()); // 인스턴스 메소드를 호출하여 사용할수 있다
구분은 간단하다 static이 안붙으면 인스턴스 메소드, 붙으면 static메소드이다.
인스턴스 메소드는 iv를 사용하고
static메소드는 lv를 사용한다.
그렇다면 static을 붙일지 말지를 언제 선택할까?
- 속성(멤버 변수) 중에서 공통 속성에 static을 붙인다.
class Card {
String kind;
int number;
static int width = 100;
static int height = 250;
이 두개는 바뀌지 않는다..
}
- 인스턴스 멤버(iv, im)을 사용하지 않는 메소드에 static을 붙인다.
class Mymath2 {
int a,b;
long add() {return a + b;} // iv를 사용
static long add(long a, long b) {return a + b;} // lv를 사용
메소드 간의 호출과 참조
- static 메소드는 인스턴스 변수(iv)를 사용할 수 없다.
class TestClass2 {
int iv;
static int cv;
void instanceMethod() {
System.out.println(iv);
System.out.println(cv);
}
static void staticMethod() {
System.out.println(iv); // 에러
System.out.println(cv);
}
}
static에서만 오류가 발생한다. 왜냐하면 iv를 사용하려고 하고있기 때문이다.
iv는 꼭 객체 생성을 하고 불러야한다.
- static 메소드는 인스턴스 메소드(im)를 사용할 수 없다.
class TestClass {
void instanceMethod() {}
static void staticMethod() {}
void instanceMethod2() {
instatnceMethod();
staticMethod();
}
static void staticMethod2() {
instanceMethod(); // 에러
staticMethod();
}
}
결국은 iv를 사용할 수 없다는것과 똑같은 내용이다.
그것이 메소드로 바뀐것 뿐이다.
static메소드는 인스턴스 메소드를 불러올수 없다.
'Java > 객체 지향' 카테고리의 다른 글
오버로딩(Overloading) & 오버라이딩(Overriding) (0) | 2023.05.08 |
---|---|
호출 스택(call stack) (0) | 2023.05.08 |
변수의 종류 (0) | 2023.05.08 |
클래스와 객체(feat. 객체 지향 언어의 역사) (0) | 2023.05.04 |
다향성 (참조변수의 형변환, instanceof 연산자) (0) | 2023.03.07 |