String name = " kim ";
name.trim();
name.toUpperCase();
System.out.println("[" + name + "]"); // [ kim ] — 아무것도 안 바뀜String은 불변이라 trim()은 새 문자열을 반환할 뿐 name을 바꾸지 않습니다.
✅ 반환값을 대입합니다.
String name = " kim ";
name = name.trim().toUpperCase();
System.out.println("[" + name + "]"); // [KIM]static String grade(int score) {
if (score >= 90) return "A";
else if (score >= 80) return "B";
// 80 미만이면? → 컴파일 오류: missing return statement
}컴파일러는 "어떤 입력이 와도 값이 돌아오는가"를 검사합니다. 마지막 else가 없으면 빠져나오는 길이 생깁니다.
✅ 마지막을 무조건 return으로 끝냅니다.
static String grade(int score) {
if (score >= 90) return "A";
if (score >= 80) return "B";
return "C";
}static int sumTo(int n) {
return n + sumTo(n - 1); // n이 0, -1, -2 ... 영원히 내려감
}
sumTo(5); // StackOverflowError기저 조건이 없으면 프레임이 끝없이 쌓입니다. 기저 조건이 있어도 n - 1이 아니라 n + 1로 쓰면 도달하지 못합니다.
✅ 기저 조건을 맨 앞에 두고, 재귀 호출이 반드시 그쪽으로 향하는지 확인합니다.
static int sumTo(int n) {
if (n <= 0) return 0;
return n + sumTo(n - 1);
}void print(Integer n) { System.out.println("Integer"); }
void print(long n) { System.out.println("long"); }
print(1); // "Integer"를 기대했지만 실제 출력: long확대 원시 변환(int→long)이 박싱(int→Integer)보다 먼저 시도됩니다(2.4).
✅ 의도가 Integer라면 명시합니다: print(Integer.valueOf(1)). 또는 이런 헷갈리는 오버로딩 자체를 피합니다.
static int f(int... a) { return 1; }
static int f(int[] a) { return 2; } // 컴파일 오류: 같은 시그니처int...는 컴파일러 입장에서 int[]와 완전히 같습니다.
✅ 하나만 둡니다. 가변 인자가 있으면 배열도 넘길 수 있으므로 int...만 남깁니다.
static int[] sorted(int[] a) {
Arrays.sort(a); // 호출자의 배열을 정렬해 버림
return a;
}
int[] orig = {3, 1, 2};
int[] s = sorted(orig);
System.out.println(Arrays.toString(orig)); // [1, 2, 3] — 원본이 바뀜배열은 주소가 복사되므로 메서드 안의 변경이 원본에 반영됩니다. "정렬본을 돌려준다"는 이름과 달리 원본이 망가집니다.
✅ 복사본을 만들어 작업합니다.
static int[] sorted(int[] a) {
int[] copy = Arrays.copyOf(a, a.length);
Arrays.sort(copy);
return copy;
}static long sum(int[] a, int i) { // 배열 합을 재귀로
if (i == a.length) return 0;
return a[i] + sum(a, i + 1);
}
sum(new int[200_000], 0); // StackOverflowError 가능구조가 재귀적이지 않은 단순 순회에 재귀를 쓰면 입력 크기만큼 프레임이 쌓입니다.
✅ 트리처럼 구조가 재귀적일 때만 재귀를, 순차 처리는 반복문을 씁니다.