- 클래스 로더, 스택(맨 밑에 main()), GC
- main 내부에서 호출하는 함수는 static (static 위한 메모리 따로 있으므로 main()과 같은 공간에 있어야 호출 가능)
- 함수의 한계 : 반환값 두개 이상 불가능
- 함수 내부에서 배열로 만들어 반환 (동일한 데이터 타입)
- 객체로 만들어 반환
- 함수 외부에서 배열로 만들어 인자로 전달, 함수 내부에서 리턴X
- 함수의 인자
- = 변수 -> 함수 내부에서 외부로 반환하지 않으면 외부 호출에 영향이 없다. (함수 외부에서 값을 복사하여 인자로 들여옴) :
call by value(data)
(원본 수정 X)
- = 배열 -> 함수 외부로 반환하지 않아도 함수 내부의 변화가 외부에서 반영된다. (배열의 주소값이 복사되어 인자로 들어옴)
파라미터와 인자의 변수명이 달라도 주소값은 같다 : call by value(address)
(원본 수정 O)
call by reference
(참조자는 C++ 개념)
package me.day06.function;
public class MainFunctionExample {
public static void main(String[] args) {
int res1 = sigma(1);
int res2 = sigma(10);
System.out.println("res1 = " + res1);
System.out.println("res2 = " + res2);
int x = 1;
int y = 2;
System.out.printf("swap 함수 외부 (전): [%d %d]\n", x, y);
swap(x, y);
System.out.printf("swap 함수 외부 (후): [%d %d]\n", x, y);
int[] res = swap2(x, y);
x = res[0];
y = res[1];
System.out.printf("swap2 함수 외부 (후): [%d %d]\n", x, y);
int[] vars = new int[]{x, y};
System.out.println(vars);
swap3(vars);
System.out.printf("swap3 함수 외부 (후): [%d %d]\n", vars[0], vars[1]);
}
public static int sigma(int n) {
int sum = 0;
for (int i = 1; i <= n; i++) {
sum += i;
}
return sum;
}
public static Aggregation sumAndAverage(int n) {
int sum = 0;
double average = 0.0;
for (int i = 1; i <= n; i++) {
sum += i;
}
average = (double) sum / n;
return new Aggregation(sum, average);
}
public static void swap(int x, int y) {
System.out.printf("swap1 함수 내부 (전): [%d %d]\n", x, y);
int temp;
temp = x;
x = y;
y = temp;
System.out.printf("swap1 함수 내부 (후): [%d %d]\n", x, y);
}
public static int[] swap2(int x, int y) {
System.out.printf("swap2 함수 내부 (전): [%d %d]\n", x, y);
int temp;
temp = x;
x = y;
y = temp;
System.out.printf("swap2 함수 내부 (후): [%d %d]\n", x, y);
return new int[]{x, y};
}
public static void swap3(int[] args) {
System.out.println(args);
System.out.printf("swap3 함수 내부 (전): [%d %d]\n", args[0], args[1]);
int temp;
temp = args[0];
args[0] = args[1];
args[1] = temp;
System.out.printf("swap3 함수 내부 (후): [%d %d]\n", args[0], args[1]);
}
}
변수와 배열의 참조
- call by reference
call by value (data)
call by value (address)
- 리턴 값 없는데 왜 순서 바뀌었을까
변수 : 다른 scope에 변수 새로 할당되고 복사된 값이 새로운 변수에 들어감 // 서로 다른 4개의 변수
배열 : 새로운 변수를 참조하지 않고 배열의 주소를 그대로 참조
- 배열
- 배열과 객체는 생성하자마자 배열의 이름에 주소값이 들어가있다. 인덱스로 모든 데이터에 접근 가능
- 배열의 전달 = 원본 배열 주소의 전달
- 값 복사 = 원본 수정X, 주소값 복사 = 원본 수정O (원본 참조)
- 일반 변수는 실제 물리적 주소값을 알기 어렵다. (C++ 에서는 포인터로 가능)
- 배열 인덱스의 시작이 0인 이유 = 주솟값 추정
(첫번째 인덱스의 주소값) + i * (int의 byte 수) = 200 + 1 * 4 = 204 = 배열 두번째 원소의 주소값
중복정의(overload)
- 함수 이름이 동일하면 매개변수의 개수, 데이터 타입, 순서로 구분
- 매개변수의 개수, 데이터 타입, 순서 까지 동일하면 컴파일 에러
- 반환형만 다른 것은 다른 함수아님
재정의(override)
함수명
- 동사가 먼저 오는게 좋음 (calculateAverage)
- 특수문자, 숫자, 키워드 X
가변인자
- 함수 여러개를 중복정의 하는 대신 가변인자(Java8) 사용 :
int ... vars
- 컴파일러는 배열 인자로 인식 :
int[] vars
package me.day06.function;
public class VarsArgExample {
public static void main(String[] args) {
sum();
sum(1);
sum(1, 2);
sum(1, 2, 3);
sum(1, 2, 3, 4, 5, 6);
}
public static int sum(int... vars) {
int sum = 0;
for (int v: vars) {
sum += v;
}
return sum;
}
}
재귀함수
- 점화식, drive and conquer(분할 정복)
- 트리로 종료구문까지 쭉 내려갔다가 계산하며 다시 올라옴. 중복되는 항의 계산이 많아 속도 느리다
- vs. for : 계산에서 중복되는 항 없다
- DFS/BFS : for문 횟수가 가능되지 않을때 고려. 결과를 보고 for문 멈춰야 할때
package me.day06.function;
public class RecursiveFunctionExample {
public static void main(String[] args) {
long res1 = fibonacciFor(10);
long res2 = fibonacciRecursive(10);
System.out.println("res1 = " + res1);
System.out.println("res2 = " + res2);
}
public static long fibonacciFor(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
int a = 0;
int b = 1;
int c = 0;
for (int i = 2; i <= n; i++) {
c = a + b;
a = b;
b = c;
}
return c;
}
public static long fibonacciRecursive(int n) {
if (n == 0) return 0;
if (n == 1) return 1;
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
}
![](https://velog.velcdn.com/images/soyoungkangme/post/836a7605-deed-4190-9bfc-4edf04e55369/image.png)