메소드
클래스가 수행하는 기능이다.
리턴타입 메소드명 (파라미터 변수1, 파라미터 변수2 ... ){ 구현내용 }
값을 반환할 때는 예약어인 return 사용한다. 호출하는 쪽에서 던지는 값을 인수(Argument, 인자) 라고 하고, 메소드에서 받는 값을 매개변수(Parameter, 파라미터) 라고 한다. 리턴 값이 없을 경우 리턴 타입에 void를 넣으면 된다. 리턴 타입이 void면 return 키워드를 사용하지 않아도 되는데 사용할 경우에는 메소드의 수행을 강제 종료하는 기능을 가지고 있다. 참고로 파라미터 변수와 인수의 데이터 타입과 순서 모두 같아야 한다!
파라미터 변수와 인자값 개념 익히기
package Method;
class Args{
int x;
void add(int x) { //파라미터
x = x + 50;
}
void add(Args arg) {
arg.x = arg.x + 40;
}
void addNew(Args arg) {
arg = new Args();
}
void add(int[] arr) {
arr[0]++;
}
}
public class ArgsTest{
public static void main(String[] args) {
Args arg = new Args(); // 객체변수 생성
arg.x = 100;
int[] arr = new int[1]; //배열만듦
arg.add(arg.x); //인자
System.out.println("arg.x = " + arg.x);
arg.add(arg);
System.out.println("arg.x = " + arg.x);
arg.addNew(arg);
System.out.println("arg.x = " + arg.x);
arg.add(arr); //인자
System.out.println("arr[0] = " + arr[0]);
}
}
여기서는 자바 소스 파일 안에 두 개의 클래스가 생성되어 있지만 실전에서는 주로 따로 나눈다고 한다. 혹여 한 파일에 두 개 이상의 클래스가 있을 때는 하나의 public(접근제한자) 클래스만 생성할 수 있다. public가 지정된 클래스 이름으로 자바 소스 파일의 이름을 지어야 한다!!
arg.x = 100 arg.x = 140 arg.x = 140 arr[0] = 1 |
Args Class부터 보면 add 메소드는 같지만 파라미터값이 다 다르다. Main에서는 객체 생성 후 변수 초기화를 해주고 있다.
arg.add(arg.x);
System.out.println("arg.x = " + arg.x);
왜 150이 아니라 100이 출력 되는 걸까? void add(int x) 메소드를 실행할 경우 x = x + 50; 이 값은 로컬변수로 stack에 저장되기 때문에 메소드를 빠져 나오면 값이 소멸된다.
arg.add(arg);
System.out.println("arg.x = " + arg.x);
똑같은 것 같은데 얘는 왜 140으로 40이 더해져서 출력이 됐을까? arg.x = arg.x + 40; 여기서 arg.x 값은 heap에 있는 x를 참조하는 값이다. 때문에 140으로 변경되었다.
arg.addNew(arg);
System.out.println("arg.x = " + arg.x);
혼자만 메소드명이 addNew이다. 여기서는 new로 객체를 새로 만들었다. 위에 있는 것을 복사해서 갖고 온 것이다.
arg.add(arr);
System.out.println("arr[0] = " + arr[0]);
메소드를 보면 값을 1 올리는 기능을 갖고 있어서 0이 아니라 1을 출력한다.
가변 인자 메소드(Variable Argments)
JDK 1.5부터 사용가능. 인자의 개수를 가변적으로 받을 수 있다. 이말인즉슨 파라미터 값이 변할 수 있다는 거다.
package Method;
public class VariableArgument {
void printInfo(String ...infos) { //가인수, 파라미터 값
if(infos.length != 0) {
for(int i=0; i<infos.length; i++) {
System.out.println(infos[i]);
}
}else {
System.out.println("인자가 없네요");
}
System.out.println("---------------------------");
}
public static void main(String[] args) {
VariableArgument vt = new VariableArgument();
//생성시킨다. 생성할 때 클래스 이름을 쓴다. 클래스 객체
//위에 있는 걸 이용하기 위해서 만들어 줌
System.out.println("인자가 없을 때 : ");
vt.printInfo();
//아무것도 없다. 인자가 없다.
System.out.println("인자가 한 개일 때 : ");
vt.printInfo("오정원");
//인수
//오정원 하나 들어가 있다.
//vt에 하나를 보내준다.
System.out.println("인자가 두 개일 때 : ");
vt.printInfo("오정원", "전산부");
//vt에 두 개를 보내준다.
System.out.println("인자가 세 개일 때 : ");
vt.printInfo("오정원", "전산부", "1억");
//vt에 세 개를 보내준다.
}
}
인자가 없을 때 : 인자가 없네요 --------------------------- 인자가 한 개일 때 : 오정원 --------------------------- 인자가 두 개일 때 : 오정원 전산부 --------------------------- 인자가 세 개일 때 : 오정원 전산부 1억 --------------------------- |
void printInfo(String ... infos) { 구현내용 }
일일이 메소드를 만들지 않고 이렇게 처리 할 수 있다. 가변 인자 메소드에서 중요한 가장 중요한 부분은 바로 이 부분이다. 잘 보면 데이터타입과 파라미터 값 사이에 ... <- 점 세개가 적혀있다! 이 부분이 컴파일러가 배열로 만들어주는 부분으로 가변인자에서 없어선 안 되는 부분이다. 참고로 ... 을 빼고 실행을 시키면 오류가 난다.
메소드 오버로딩(OverLoading)
같은 이름의 메소드를 한 클래스에 여러개 정의 할 수 있다. 이런 메소드 오버로딩이 성립하기 위해선 파라미터의 타입이나 개수가 달라야 한다.
void printInfo(int x);
void printInfo(String x);
void printInfo(String x, String y);
변수이름이나 리턴타입은 성립에 영향을 주지 않는다.
void printInfo(String x);
void printInfo(String name); //안됨
void printInfo(String name);
int printInfo(String name); //안됨
class Boiler{
int temp;
void temp() {
temp++;
}
void temp(int amount) {
temp += amount;
}
}
public class OverloadingTest {
public static void main(String[] args) {
Boiler boiler = new Boiler();
System.out.println("현재 온도 : " + boiler.temp );
boiler.temp();
System.out.println("boiler.temp() 호출 후 현재 온도 : " + boiler.temp );
boiler.temp(10);
System.out.println("boiler.temp(10) 호출 후 현재 온도 : " + boiler.temp );
}
}
현재 온도 : 0 boiler.temp() 호출 후 현재 온도 : 1 boiler.temp(10) 호출 후 현재 온도 : 11 |
메소드 사용하고 출력을 해준다. 온도를 출력할 때 호출하는 값은 항상 같다. (boiler.temp)
temp() 인자 값 자리를 비우면 온도 1을 올리고, 숫자를 넣으면 현재 온도에 그 값을 더해주도록 설정했다.
static 메소드와 인스턴스 메소드
이것은 변수와 다르다. 큰 차이점은 호출 조건이다. 스태틱의 경우 객체생성을 하지 않아도 자유롭게 호출 가능하다. 인스턴스는 꼭 객체 생성을 하고 호출을 해야한다. 또한 static 예약어가 붙으면 인스턴스 보다 초기화 시점이 빠르기 때문에 스태틱 메소드 안에서는 인스턴스 변수와 인스턴스 메소드를 사용할 수 없다. 참조하고 싶다면 객체 생성 후에 객체를 통해서 참조하면 된다!!
인스턴스/스태틱 변수와 메소드 차이는 () <- 소괄호 유무로 판단할 수 있다.
public class StaticMethod {
//Instance Member Variable
int memVar;
//Static Member Variable
static int staticVar;
//Instance Method
void memMethod1() {
int local = memVar;
local = staticVar;
staticMethod1();
memMethod2();
System.out.println("memMethod1");
}
void memMethod2() {
System.out.println("memMethod2");
}
//Static Method
static void staticMethod1() {
//int local = memVar;
//memMethod1()
StaticMethod st = new StaticMethod();
int local = st.memVar;
st.memMethod2();
staticMethod2();
System.out.println("staticMethod1");
}
static void staticMethod2() {
System.out.println("staticMethod2");
}
//메인 메소드(스태틱)
public static void main(String[] args) {
//StaticMethod.memMethod1();
StaticMethod st = new StaticMethod();
st.memMethod1();
StaticMethod.staticMethod2();
staticMethod2();
int local = staticVar;
//local = memVar;
}
}
인스턴스 메소드 안에서는
인스턴스 변수 int local = memVar;
static 변수 local = staticVar;
static 메소드 staticMethod1(); 모두 사용가능!!
같은 클래스 안에 있는 인스턴스 메소드끼리는 상호호출도 가능!! memMethod2();
static 메소드 안에서는
인스턴스 변수 int local = memVar;
인스턴스 메소드 호출할 수 없다. memMethod1();
사용하고 싶다면 객체 생성 후에 사용할 수 있다.
다른 static 변수는 사용 가능하다.
memMethod2 staticMethod2 staticMethod1 memMethod2 memMethod1 staticMethod2 staticMethod2 |
'개발일지 > Java + Spring' 카테고리의 다른 글
[Java] 생성자(Constructor), this() 생성자, 초기화 블록 (0) | 2021.09.29 |
---|---|
[Java] 성적 입출력 - 클래스로 나누기, 소수점 n번째 자리 (0) | 2021.09.28 |
[Java] 클래스 정의와 변수의 3가지 종류 (0) | 2021.09.27 |
[Java] 0924 클래스의 구조 / 상위 클래스를 상속 받은 클래스 (0) | 2021.09.24 |
[Java] 팩토리얼 + 피보나치 수열로 재귀함수 배우기 (0) | 2021.09.22 |