Java/Java로 배우는 자료구조

자료구조 2-1. 클래스, 객체, 참조변수(2)

성장코딩 2023. 2. 13. 03:04

Theme. 클래스, 참조변수, 객체의 관계

 

클래스는 type이다.

클래스에 대해 비유적으로 얘기해보자면, 

어떤 집을 짓는다고 할때, 클래스는 마치 하나의 설계도와 같다고 말할 수 있다. 우리가 설계도 안에서 가구를 놓고 살 수 없듯이  설계도는 집을 만들기 위한 도면일 뿐, 실제로 존재하는 집은 아니다.

마찬가지로 클래스 자체에 어떤 데이터를 저장하거나, 클래스 안에 있는 데이터를 읽거나 등등을 하는 것이 아니라 클래스는 객체나 참조변수 등을 만들어 내기 위해 그 객체나 참조변수의 타입을 정의하는 등의 역할을 하는 하나의 설계도일 뿐이다. 반면에 객체는 설계도가 아니라 이를 통해 지어진 집이라고 표현할 수 있다. 

클래스 vs 참조변수, 객체의 구도를 나눈다고 했을 때, 참조변수나 객체가 실체가 되고, 클래스는 허상이라고 생각할 수 있다. 

Person a = new Person(); 에서 

Person 타입의 객체를 new 연산자를 통해 만들었고, 그 객체의 주소를 저장하는(객체를 가리키는) 참조변수 a가 존재한다. 

이때, new 연산자를 통해 생성된 객체 그 자체는 이름이 없으므로 이때 참조변수가 필요한 것이다.

 

 

Theme. 객체와 참조변수의 사용시 주의할 부분

 

어떤 클래스의 객체를 생성하고, 객체의 참조변수를  통해 객체에 접근하는 구조에 대해 이해를 하고 있더라도 코드를 작성하는 과정에서 놓칠 수 있는 부분이 있다. 그 놓칠 수 있는 부분에 대해 아래 예제와 함께 알아보도록 하자.

 

 

위 예제를 해결하기 위해,  아래와 같이 클래스를 생성하였다.1. MyPoint1.java - x좌표와 y좌표를 선언한 클래스          public class MyPoint1 {
        public int x;
        public int y;
    }

 

2. MyRectangle1.java - 어떤 직사각형에 대한 정보를 나타낸 클래스

 

1
2
3
4
5
6
7
package Section1;
 
public class MyRectangle1 {
    public MyPoint1 lu; // 왼쪽 위의 꼭짓점의 좌표(left-up)
    public int width; // 너비
    public int height; // 높이
}
cs

이때, 주의할 것은 lu라는 변수는 MyPoint1 타입이다. 

 

3. Code05.java - main 메서드가 포함된 클래스

 

먼저, 전체적인 코드를 살펴보고 설명을 하도록 한다.

 

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
package Section1;
 
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
 
public class Code05 {
 
    static MyRectangle1[] rects = new MyRectangle1[100]; // 사각형들의 배열
    static int n = 0// 배열에 저장된 사각형의 개수 n
 
    public static void main(String[] args) {
 
        try {
            Scanner sc = new Scanner(new File("data.txt"));
 
            while (sc.hasNext()) {
                rects[n] = new MyRectangle1(); // 배열의 한 칸이 참조할 객체를 생성
                rects[n].lu = new MyPoint1(); 
 
                rects[n].lu.x = sc.nextInt(); // x 좌표
                rects[n].lu.y = sc.nextInt(); // y 좌표
                rects[n].width = sc.nextInt(); // 너비
                rects[n].height = sc.nextInt(); // 높이
                n++;
            }
            sc.close();
        } catch (FileNotFoundException e) {
            System.out.println("No data file.");
            System.exit(1); // 프로그램 종료
 
        }
 
        bubbleSort();
 
        for (int i = 0; i < n; i++) {
            System.out.println(rects[i].lu.x + " " + rects[i].lu.y + " " + rects[i].width + " " + rects[i].height);
 
        }
 
    }
 
    public static void bubbleSort() {
        for (int i = n - 1; i > 0; i--) {
            for (int j = 0; j < i; j++) {
                if (calArea(rects[j]) > calArea(rects[j + 1])) {
                    MyRectangle1 tmp = rects[j + 1];
                    rects[j + 1= rects[j];
                    rects[j] = tmp;
                }
            }
        }
 
    }
 
    // 사각형의 면적을 구하는 함수 calArea
    public static int calArea(MyRectangle1 r) {
        return r.width * r.height;
    }
}
 
cs

 

사각형의 면적을 구하고 이를 정렬하는 것은 간단한 문제이니 생략하도록 하고,

while문을 자세히 살펴보도록 한다.

 

1
2
3
4
5
6
7
8
9
10
while (sc.hasNext()) {
                rects[n] = new MyRectangle1(); // 배열의 한 칸이 참조할 객체를 생성
                rects[n].lu = new MyPoint1(); 
 
                rects[n].lu.x = sc.nextInt(); // x 좌표
                rects[n].lu.y = sc.nextInt(); // y 좌표
                rects[n].width = sc.nextInt(); // 너비
                rects[n].height = sc.nextInt(); // 높이
                n++;
            }
cs

 

MyRectangle1[] rects = new MyRectangle1[100]; 와 같이

먼저, rects라는 참조변수가 가리키는 객체는 MyRectangle1 타입의 배열이다. 

즉, rects라는 참조변수는 "배열"을 가리킨다.

 

rects[n] 또한 MyRectangle1 타입의 참조변수로 배열의 한 "칸"에 해당한다. 

즉, 배열의 각 칸은 rects[n]이라는 참조변수를 통해 객체에 접근한다.

 

처음 배열을 선언할 때, 참조변수 rects가 MyRectangle1의 객체를 참조하도록 하였지만,

참조변수 rects[n]은 아직 그러한 부분이 작성되지 않았고, 이를 위해 while문에 

rects[n] = new MyRectangle1(); // 배열의 한 칸이 참조할 객체를 생성
rects[n].lu = new MyPoint1(); 

과 같이 코드를 작성한 것이다. 

rects[n].lu의 부분은 MyRectangle1의 객체를 가리키는 것이 아니라, MyPoint1의 객체를 가리키고, 그 안에 존재하는 x,y 좌표의 값에 접근하기 위해 작성되었다. 

( main 메서드  -----> MyRectangle1 클래스  -----> MyPoint1 클래스)

 

 

결론적으로, 참조변수가 어떤 값을 참조하도록 할 때, 그 참조변수가 참조할 수 있는 객체가 선언되어 있는지를 반드시 확인하고 그렇지 않다면 선언해주도록 하자!