메서드인지 메소드 인지 매번 헷갈려요ㅠ
1. 메소드 기본
- 자주 사용하는 코드를 뽑아서 묶어놓은 것
- 메서드 선언 방법
void 메서드이름(){
코드;
}
- 예를 들어 별찍기 코드를 자주 사용한다면 이 코드를 묶어서 하나의 메서드로 만들고 이후 메인 메서드에서 빠르게 실행 할 수 있다.
- 메서드에서 다른 메서드를 불러 올 수도 있다.
public static void main(String[] args) {
int count = 0;
PrintStar();
PrintStar();
PrintStar();
for(int i=0; i<3; i++) {
count++;
PrintStar();
System.out.println("count : "+count);
}
}
// 별찍기 메서드 생성
static void PrintStar() {
for(int i=1; i<=5; i++) {
for(int j=1; j<=i; j++) {
System.out.print("*");
}
System.out.println();
}
}
2. 메서드 매개변수 - void
- 메서드에서 ( ) 안에 있는 값을 매개변수, 인자, 아큐먼트 라고 한다.
- 메서드의 매개변수에서 넘어오는 값은 이후 메서드 안에서 유동적으로 할당되어 사용이 가능하다.
- 아래 구구단 코드에서 num 값을 매개 변수로 받았고, 이를 사용해서 num 단을 출력한다.
- 이때 매개 변수로 주는 타입과 메서드에서 선언된 타입은 일치해야 한다.
void 매서드명(자료형 매개변수){
코드;
};
- void 는 매서드 실행 후 호출한쪽으로 아무값도 리턴하지 않는다.
## 메인 메서드 ##
System.out.println("-------------------------");
printGuGuDan(2);
printGuGuDan(6);
printGuGuDan(8);
####
static void printGuGuDan(int num) {
for(int j=1; j<=9; j++) {
System.out.println(num+" 단 : "+num+" * "+j+" = "+num*j);
}
}
3. 메서드 - 반환타입 & return
- void 대신 반환하고자하는 자료형 - int , String - , 배열 등등을 메서드명 앞에 쓸 수 있다.
- 자료형 뿐만 아니라 객체도 쓸 수 있다.
- 반환 타입이 있는 메서드에서는 반드시!! return 이 포함되어야하며, return 뒤에는 메서드 실행 후 호출한 곳으로 return 뒤에 있는 값을 보내준다.
- 메서드는 호출한 쪽에는 return 값을 제외한 다른 값에는 영향을 주지 않는다.
public static void main(String[] args) {
// 반환된 결과를 result2 에 저장
int result2 = minus(100,200);
System.out.println(result2);
}
// int 타입의 결과를 반환하는 메서드
static int minus(int a, int b) {
int c = a - b;
// 결과를 c 에 담아서 반환
return c;
}
######### 큰 값 구하기 ############
System.out.println("---------------");
int max = max(350,200);
System.out.println(max);
static int max(int a, int b) {
int max = 0;
if(a>b) {
max = a;
}else {
max = b;
}
return max;
}
4. 메서드 오버로딩 : 매서드의 이름과 매개변수
- 메서드 오버로딩은 메서드 명은 동일하나 매개변수의 갯수, 순서, 타입을 다르게 만들면 오버로딩이 된다.
- 중요한 것은 매개 변수의 갯수, 순서, 타입 3가지 중 하나만 달라도 메서드는 그것을 서로 다른 메서드라고 인식하고, 오버로딩 되었다고 할 수 있다.
- 매서드는 서로 이름이 동일하더라도 매개변수와 반환 타입이 달라지면 서로 다른 메서드로 인식한다.
- 즉 똑같은 max 메서드라도 매개변수가 max(int, int) 인 메서드와 max(int, float) 인 메서드는 서로 다르다.
#### 서로 이름은 같지만 기능은 다른 메서드 => 오버로딩된 메서드
static int sum(int a, int b, int c) {
return a+b+c;
}
static int sum(int a, int b, int c, int d) {
return a+b+c+d;
}
static int sum(int a, float b, int c) {
return a + (int)b + c;
}
################ ####################
System.out.println("---------------");
int result4 = max(110, 210.0f);
System.out.println(result4);
#####
static int max(int a, float b) {
if(a > b) {
return a;
}else {
return (int)b;
}
}
5. 메서드 매개변수 - 고정인자
- 메서드의 매개변수는 기본적으로 매서드 선언부에 괄호 안에 선언된 매개변수의 갯수 - ( ) - 만큼만 올 수 있다.
- 아래처럼 똑같은 avg 메소드를 매개 변수의 갯수만 다르게해서 오버로딩하여 사용 가능하다.
static int avg(int a, int b) {
int avg = (a+b)/2;
return avg;
}
static int avg(int a, int b, int c) {
int avg = (a+b+c)/3;
return avg;
}
static int avg(int a, int b, int c, int d) {
int avg = (a+b+c+d)/4;
return avg;
}
6. 메소드 매개변수 - 가변인자
- 매서드의 매개변수는 고정된 값만을 받는것이 아니다.
- 즉 만약 매개변수 100개 , 1000를 받아야 하는 상황 일 때 선언부에 매개 변수의 갯수를 일일히 적어주지 않아도 된다는 것이다.
- 매개변수를 내가 원하는 만큼 받을 때, 혹은 받아야 하는 매개 변수의 갯수를 모르는 경우 사용하는 방법이 가변 인자 이다 ⇒ 가변 파라미터
- 가변인자는 메서드명(자료형 ... 변수명) 으로 사용한다 => 이때 ... 은 정말 사용하는 ... 이다.
- 이렇게 가변인자를 받게 될 때는 메서드의 인자를 해당 자료형의 배열로 취급한다.
- 배열로 취급하기 때문에 .length 사용이 가능하다.
- void Method(int ... num){ => 이라고 할 때 매개변수 num 은 메서드 안에서 사용될 때는 일종의 배열로 취급되어 사용된다.
// 만약 매개변수를 처음부터 지정하는 것이 아니라 내가 원할때마다 바뀌는 값만큼을 받고 싶다면 어떻게할까?
// 이때 가변 인자를 사용한다.
// 매개변수에서 ... 을 사용하면 가변 인자를 사용하게 된다.
// 이때 사용되는 가변인자는 일종의 배열로 취급된다.
static int avg(int ... data) { // 가변인자 data
int sum = 0;
System.out.println("data : "+data);
for(int r : data) {
System.out.print(r+" ");
}
System.out.println();
// 배열로 취급되기 때문에 인자 data 를 사용해 인자의 총 갯수를 알아볼 때
// data.length 를 사용할 수 있다 => data 배열의 길이 = 총 매개 변수의 갯수
for(int i=0; i<data.length; i++) {
sum+=data[i];
}
return sum/data.length;
}
7. 메서드 호출 방식
- call by value : 메소드로 인자값을 넘길 때, 그 값을 복사하여 넘기기 때문에 메소드 내에서는 복사된 값으로 작업을 하고, 원래의 값을 변경시키지 않는다.
- 기존 변수의 주소값을 다른 곳에 복사해두고, 복사한 곳에서 작업을 하기 때문에 기존 변수의 주소값에 영향을 미치지 않는다 => 기존변수와 메서드 인자가 바라보는 주소값이 달라짐!!
- call by reference : 메서드의 매개변수로 주소값을 넣어서 전달하는 경우, 즉 객체나 배열 등의 값을 전달하는 경우 메서드 내에서 변화가 있을 때 이 변화한 내용이 객체나 배열에도 그대로 반영됨 => 기존 변수와 메소드 인자가 바라보는 - 참조하는 - 주소값이 동일!! 서로의 작업에 영향을 미친다.
- 메소드로 인자값을 넘길 때, 그 객체를 참조하는 주소를 넘기기 때문에 메소드 내에서 원래의 값에 접근이 가능하며 변경시킬 수 있다.
- 배열처럼 참조 타입들은 - ex) 객체 - 메서드에 인자로 넘겼을 때 call by value 처럼 주소를 복사해서 다른곳에 옮겨두고 사용하는 것이 아니라 같은 주소를 참조하면서 사용하기 때문에 메서드 내에서의 변경, 수정이 메서드 밖의 num 배열에도 영향을 미친다.
public class Quiz02_3 {
public static void main(String args[]) {
// method 호출방법에 따라서 크게 2가지로 분류된다.
// 첫째는 call by value 로 아래와 같이 매개변수로 주소값이 아닌 주소를 복사한 값을
// 전달하는 방식으로 이는 주소를 복사한 값이기 때문에 기존 변수에 영향을 주지 않는다.
int a = 2;
int b = 6;
printGuGuDan(a, b); // 구구단을 사용하는것은 call by value
// 두번째는 call by reference 로 메서드에 인자값을 넘길때 해당 변수의 주소값을 넘기기 때문에
// 메서드에서 해당 주소값을 접근할 수 있게 되고, 메서드 내에서 변경가능하며
// 기존 변수에도 영향을 미친다.
// 아래에서 num 배열과 메서드안에서 사용하는 a 배열의 주소값은 동일!
// 배열처럼 참조 타입들은 - ex) 객체 - 메서드에 인자로 넘겼을 때
// call by value 처럼 주소를 복사해서 다른곳에 옮겨두고 사용하는 것이 아니라
// 그냥 같은 주소를 쓰면서 사용하기 때문에 메서드 내에서의 변경, 수정이
// 메서드 밖의 num 배열에도 영향을 미친다.
int[] num = {1,2,3,4,5};
System.out.println("메서드에서 매개변수 a 배열의 주소값 : "+num);
Arraysum(num);
}
static void printGuGuDan(int a, int b) {
for(int i=a; i<=b; i++) { // 인자로 넘겨받는 a 부터 b 까지 구구단 출력
for(int j=1; j<=9; j++) {
System.out.println(i+" 단 : "+i+" * "+ j +" = "+i*j);
}
System.out.println("-----------");
}
}
static void Arraysum(int[] a) {
System.out.println("메서드에서 매개변수 a 배열의 주소값 : "+a);
int sum = 0;
for(int i=0; i<a.length; i++) {
sum += a[i];
}
System.out.println("sum = "+sum);
}
}
8. 메서드의 매개변수와 참조값
- 앞에서 설명하였듯 call by Reference 의 경우 매개변수로 넘어오는 변수의 주소값으 그대로 복사해서 사용하는 것이 아닌 해당 변수의 주소값을 그대로 참조하여 사용한다.
- 이 때문에 메서드안에서의 변경, 수정이 해당 변수에독 그대로 반영되는 결과 갖는다.
- 이렇게 참조값을 그대로 사용하는 변수의 타입을 Reference type - 참조형 타입 -이라고 하며 아래의 4가지 타입이 이에 해당한다
타입 | 예시 | 기본값 | 할당되는 메모리 크기 |
배열 Array | int[] arr = new int[5] | Null | 4byte |
열거 | Null | 4byte | |
클래스 class | Music m = new Music(); | Null | 4byte |
인터페이스 interface | Null | 4byte |
9. 공부 정리 - StarCraft 마린으로 알아보기
- 오늘의 공부를 정리해보기 위해 스타크래프트 마린을 한마리 불러오도록 하겠다.
- 먼저 마린의 hp, 위치 좌표, 사거리, 공격력, 방어력, 이동 속도, 공격 속도 등을 정의할 수 있는 필드 변수를 선언한다.
- 이후 생성자를 이용해서 기본 마린의 능력치를 정의한다.
package day7;
public class Marine {
// member 변수, 필드
int hp, x, y, range, at_point, de_point;
int at_speed, mo_speed;
Marine(){
// 기본 생성자
// 1. 클래스명과 동일한 이름을 갖는 메서드
// 2. 객체의 초기화를 담당
// 3. 리턴값이 없지만 void 키워드 사용 X, void 가 있다면 생성자가 아닌 일반 메서드
// 4. 생성자는 여러개를 갖을 수 있음
hp = 50;
range = 3;
at_speed = 2;
mo_speed = 3;
at_point = 5;
de_point = 1;
x = 0;
y = 0;
System.out.println("기본 생성자 실행");
}
Marine(int hp, int x, int y, int at_point, int mo_spd){
// 참조변수 this. 를 사용해서 매개변수의 값을 인스턴스 변수에 넣는다
this(300, 200, 100);
this.at_point = at_point;
this.mo_speed = mo_spd;
}
void attack(Marine m) {
// 매개변수 m 에 들어오는 값은 starCraft 의 객체만 올 수 있음
// 매개변수 m 은 메서드 실행 시 들어오는 인자의 참조 - 주소 -값을 그대로 사용함
System.out.println("공격하기 메소드의 m : "+m);
System.out.println(m+ " 에게 공격 중!!");
// 때문에 아래처럼 m.hp 를 찍었을 때 들어오는 인자의 주소값을 보고 hp 를 찾아 갈 수 있고
// hp 를 깎는 공격 기능을 실행 할 수 있다
m.hp -= at_point;
}
void move() {
x += (int)(Math.random()*10)+1;
y += (int)(Math.random()*10)+1;
System.out.println("move, move, move");
}
void stop() {
System.out.println("stop!!");
}
boolean UseStimPack() {
// 스팀팩 사용하면 체력이 약간 감소
if(hp > 10) {
hp -=10;
at_speed +=3;
mo_speed +=3;
System.out.println("오우~~예~~");
return true;
}else {
System.out.println("체력이 부족합니다");
return false;
}
}
void patrol() {
System.out.println("정찰 중");
}
void status() {
System.out.println("나는 마린");
System.out.println("체력 : "+hp);
System.out.println("x : "+x+" y : "+y);
System.out.println("attack point : "+at_point);
System.out.println("depend point : "+de_point);
System.out.println("attackSpeed : "+at_speed);
System.out.println("moveSpeed : "+mo_speed);
}
}
- 이렇게 생성된 마린 객체를 2개 생성 후 status 를 통해 현재 상태를 확인한다.
// 공격을 실행할 마린 m1
Marine m1 = new Marine();
m1.status();
System.out.println("------------------------------");
// 공격을 당할 마린 m2
Marine m2 = new Marine();
m2.status();
--- 결과 ----
기본 생성자 실행
나는 마린
체력 : 50
x : 0 y : 0
attack point : 5
depend point : 1
attackSpeed : 2
moveSpeed : 3
------------------------------
기본 생성자 실행
나는 마린
체력 : 50
x : 0 y : 0
attack point : 5
depend point : 1
attackSpeed : 2
moveSpeed : 3
- attack() 메서드를 통해 마린을 공격해보자
- 이제 실행시켜보면 공격하기 메소드 m 의 주소값과 ~~에게 공격중에서 나오는 주소값이 모두 동일한 것을 알 수 있다.
- 이후 m2 의 status 를 다시 확인해보면 m1 의 공격력만큼 hp가 감소한 것도 확인 할 수 있다. 즉 객체가 매개변수로 넘오는 경우 해당 객체의 주소값을 그대로 참조하며, 메서드를 통한 변동 - hp 감소 - 가 m2 객체의 인스턴스 변수에 반영된 것을 확인 할 수 있다.
##### Marine 메서드 ######
void attack(Marine m) {
// 매개변수 m 에 들어오는 값은 starCraft 의 객체만 올 수 있음
// 매개변수 m 은 메서드 실행 시 들어오는 인자의 참조 - 주소 -값을 그대로 사용함
System.out.println("공격하기 메소드의 m : "+m);
System.out.println(m+ " 에게 공격 중!!");
// 때문에 아래처럼 m.hp 를 찍었을 때 들어오는 인자의 주소값을 보고 hp 를 찾아 갈 수 있고
// hp 를 깎는 공격 기능을 실행 할 수 있다
m.hp -= at_point;
}
############ Main 메서드 #########
System.out.println("------------------------------");
m1.attack(m2);
m2.status();
#### 결과 ####
System.out.println("------------------------------");
공격하기 메소드의 m : day7.Marine@436e852b
day7.Marine@436e852b 에게 공격 중!!
나는 마린
체력 : 45
x : 0 y : 0
attack point : 5
depend point : 1
attackSpeed : 2
moveSpeed : 3
참고 자료
- 자바 메서드 호출 방식 2종류
https://velog.io/@ahnick/Java-Call-by-Value-Call-by-Reference
[Java] Call by Value, Call by Reference
프로그래밍 언어들의 메소드 매개변수 호출 방식에는 여러 가지가 있으며 호출 방식은언어마다 다르게 되어 있습니다. 그 중 자바의 Call by Value 방식에 대해 알아봅시다 !...
velog.io
'Java - 기본기' 카테고리의 다른 글
클래스, 메서드, 생성자, 상속 정리 : 나만의 StarCraft (0) | 2022.03.01 |
---|---|
21. 접근제어자와 상속, 오버라이드 (0) | 2022.03.01 |
20. 컬렉션 프레임워크 : list, set, map 간단 하게 알아보기 (0) | 2022.02.07 |
19. 오버로딩, 생성자, 기본 생성자, 생성자 this(), 참조변수 this (0) | 2021.12.09 |
18. 메소드 : 선언부와 구현부, 메서드 호출, return문, 반환값 (0) | 2021.10.26 |
댓글