Home [코딩테스트] Java 정리 - 3
Post
Cancel

[코딩테스트] Java 정리 - 3

코딩테스트에서의 클래스와 메서드에 대해 간단히 정리했습니다.

1️⃣ 클래스와 객체

클래스 정의와 필드/생성자/메서드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 파일: Main.java (보통 public class Main, public 클래스는 하나만 가능)
class Point {                    // (public 생략 → 같은 파일에서만 사용 가능)
    int x;                       // 필드(인스턴스 변수)
    int y;
    static int val = 10;         // 클래스(static) 변수

    // 기본 생성자 (생략 가능)
    Point() {}

    // 생성자 오버로딩
    Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    // 인스턴스 메서드 (객체 상태 사용)
    int manhattan() {
        return Math.abs(x) + Math.abs(y);
    }

    // static 메서드 (객체 상태 없이 동작)
    static int distanceSquared(Point a, Point b) {
        int dx = a.x - b.x, dy = a.y - b.y;
        return dx*dx + dy*dy;
    }
}

객체 생성/사용

1
2
3
Point p = new Point(3, -4);   // 생성
int m = p.manhattan();        // 인스턴스 메서드 호출
int d2 = Point.distanceSquared(p, new Point(0, 0)); // static 메서드는 클래스명.메서드

2️⃣ 함수(메서드)

메서드 정의

1
2
3
4
5
6
7
8
9
반환타입 메서드이름(매개변수들) {
    // 로직
    return ;   // void면 생략
}

static int gcd(int a, int b) {         // 인스턴스 변수를 사용하지 않음 → static 적합
    while (b != 0) { int t = a % b; a = b; b = t; }
    return a;
}

메서드 오버로딩

1
2
static int sum(int a, int b) { return a + b; }
static long sum(long a, long b) { return a + b; } // 같은 이름, 파라미터 다름

가변인자

1
2
3
4
static int sumAll(int... nums) {
    int s = 0; for (int v : nums) s += v;
    return s;
}

3️⃣ static vs non-static

구분static (정적)non-static (인스턴스)
소속클래스에 소속 (전체 공유)객체(인스턴스)에 소속 (객체마다 별도)
수명클래스가 메모리에 올라갈 때 → 종료/클래스 언로드 시까지new 할 때마다 생성 → 인스턴스가 소멸할 때 (가비지 컬렉터가 회수)
메모리메소드(Static) 영역힙 영역
접근 방식클래스명.필드/메서드()참조변수.필드/메서드() (객체 필요)
인스턴스 멤버 접근불가 (this 없음, 인스턴트보다 static이 먼저 생성됨)가능
쓰임새유틸성 함수, 전역 상수/공유 상태, 캐시객체 상태 기반 동작, 다형성/캡슐화
오버라이딩불가(정확히는 숨김/hiding)가능 (다형성)
스레드 안전공유하므로 주의 필요객체별로 분리되어 상대적으로 안전

4️⃣ Main과 보조 클래스 배치

자바 규칙: 한 파일엔 public 최상위 클래스 1개만 허용 (파일명과 동일)
코테에선 보통 public class Main만 public이고, 그 외 클래스는 두 방법 모두 가능

(A) 최상위(Top-Level) 비공개 클래스로 Main 바깥에 배치

  • 장점 : 깔끔, 일반 자바와 동일한 패턴
  • 주의 : public 붙이면 컴파일 에러
1
2
3
4
5
6
7
8
public class Main {
    public static void main(String[] args) {}
}

class Node {  // public 없음
    int v, w; 
    Node(int v, int w){ this.v=v; this.w=w; } 
}

(B) Main 안에 중첩 클래스로 배치

  • static class는 바깥 인스턴스 없이 독립적이라 사용 간단
  • non-static inner class는 new Main().new Node()처럼 외부 인스턴스 필요 → 비추천
1
2
3
4
5
6
7
8
9
10
11
public class Main {
    static class Node { // 권장
        int v, w; 
        Node(int v, int w){ this.v=v; this.w=w; } 
    }
    // non-static class Node { ... } // 비권장: 바깥 Main 인스턴스가 필요해져 번거로움

    public static void main(String[] args) {
        Node n = new Node(1, 3); // static 중첩 클래스는 바로 생성 가능
    }
}

5️⃣ 코딩테스트에선?

  • 상태를 안 쓰는 함수(예: 파싱, 수학, 그래프 유틸) → static 메서드가 간단/빠름
  • 공유 상수/공통 배열(예: 방향 배열) → static final 상수로 선언
  • 문제 모델링용 구조체/노드 → 보통 static 중첩 클래스로 정의
  • 단, 전역 static 가변 상태는 테스트 케이스 반복 시 초기화 누락 버그 주의 (init() 함수)

지역 변수 사용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import java.io.*;
import java.util.*;

public class Main {
    // ✅ 전역 상수/배열 (예: 방향 벡터)
    static final int[] DX = {-1, 1, 0, 0};
    static final int[] DY = {0, 0, -1, 1};

    // ✅ 자료구조용 static class
    static class Node implements Comparable<Node> {
        int x, y, dist;
        Node(int x, int y, int dist) {
            this.x = x; this.y = y; this.dist = dist;
        }
        @Override
        public int compareTo(Node o) {
            return Integer.compare(this.dist, o.dist); // 우선순위 큐용
        }
    }

    // ✅ 유틸 함수 예시
    static int gcd(int a, int b) {
        while (b != 0) { int t = a % b; a = b; b = t; }
        return a;
    }

    static int lcm(int a, int b) {
        return a / gcd(a, b) * b;
    }

    static boolean inRange(int x, int y, int n, int m) {
        return (0 <= x && x < n && 0 <= y && y < m);
    }

    // ✅ 문제 풀이 함수 (호출 시 지역 변수 자동 초기화)
    static void solve(BufferedReader br, StringBuilder sb) throws Exception {
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken());

        // 2차원 배열 입력
        int[][] grid = new int[n][m];
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) {
                grid[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        // BFS 예시
        boolean[][] visited = new boolean[n][m];
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[]{0, 0});
        visited[0][0] = true;

        while (!q.isEmpty()) {
            int[] cur = q.poll();
            int x = cur[0], y = cur[1];
            for (int d = 0; d < 4; d++) {
                int nx = x + DX[d], ny = y + DY[d];
                if (inRange(nx, ny, n, m) && !visited[nx][ny] && grid[nx][ny] == 0) {
                    visited[nx][ny] = true;
                    q.offer(new int[]{nx, ny});
                }
            }
        }

        sb.append("탐색 완료\n");
    }

    // ✅ main: 입출력 전담
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int T = 1;
        // 여러 테스트케이스 지원 시: T = Integer.parseInt(br.readLine());
        for (int t = 0; t < T; t++) {
            solve(br, sb);
        }

        System.out.print(sb);
    }
}

전역 변수 사용 (init 함수)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import java.io.*;
import java.util.*;

public class Main {
    // 전역 상수
    static final int[] DX = {-1, 1, 0, 0};
    static final int[] DY = {0, 0, -1, 1};

    // 전역 변수 (테스트케이스마다 초기화 필요할 때 사용)
    static int n, m;
    static int[][] grid;
    static boolean[][] visited;

    // ✅ init 함수
    static void init(int n, int m) {
        // 전역 변수 초기화
        Main.n = n;
        Main.m = m;
        grid = new int[n][m];
        visited = new boolean[n][m];
    }

    // ✅ 유틸 함수
    static boolean inRange(int x, int y) {
        return (0 <= x && x < n && 0 <= y && y < m);
    }

    // ✅ 문제 풀이 함수
    static void solve(BufferedReader br, StringBuilder sb) throws Exception {
        StringTokenizer st = new StringTokenizer(br.readLine());
        n = Integer.parseInt(st.nextToken());
        m = Integer.parseInt(st.nextToken());

        // init으로 초기화
        init(n, m);

        // grid 입력
        for (int i = 0; i < n; i++) {
            st = new StringTokenizer(br.readLine());
            for (int j = 0; j < m; j++) {
                grid[i][j] = Integer.parseInt(st.nextToken());
            }
        }

        // BFS 예시
        Queue<int[]> q = new ArrayDeque<>();
        q.offer(new int[]{0, 0});
        visited[0][0] = true;

        while (!q.isEmpty()) {
            int[] cur = q.poll();
            int x = cur[0], y = cur[1];
            for (int d = 0; d < 4; d++) {
                int nx = x + DX[d], ny = y + DY[d];
                if (inRange(nx, ny) && !visited[nx][ny] && grid[nx][ny] == 0) {
                    visited[nx][ny] = true;
                    q.offer(new int[]{nx, ny});
                }
            }
        }

        sb.append("탐색 완료\n");
    }

    // ✅ main 함수
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringBuilder sb = new StringBuilder();

        int T = 1;
        // 여러 테스트 케이스
        // T = Integer.parseInt(br.readLine());

        for (int t = 0; t < T; t++) {
            solve(br, sb);
        }

        System.out.print(sb);
    }
}
This post is licensed under CC BY 4.0 by the author.