자료형의 구조 무조건 이해하게 정리(기본자료형, 참조자료형)Reference

BackEnd

기본자료형과 참조자료형에 대한 개념을 정리하려고 한다.

 

* 전체코드는 하단에 있으니 혹시 필요하다면 하단 참고 *

 

기본자료형이란?

 

int, float, double, long, boolean 을 예로 들 수 있고

특징으로는 모두 소문자로 이루어져있다는 것이다.

 

그리고 기본 자료형은 메서드를 가지지 않는다.

기본자료형은 복사라는 개념이 있는데 

 

예를 들어서 

 

int a = 110;

int b = 20; 

 

이렇게 작성해주고 a와b를 출력해보면

 

110

20 

 

이렇게 출력이 될 것이다.

 

만약 b=a; 라고 적어주고 다시 출력해보면

 

a = 110

b = 110

 

이렇게 출력이 된다. 

 

그 말은 즉 b =a 라는 것은 a를 복사해서 b에 넣는다는 것으로

쉽게말해 b를 a와 같은 값으로 덮어쓰겠다는 것이다.

 

a와 b 둘 사이에 뭔가 커넥션이 있어서 연결되어진 것이 아니라 단순히 긁어서 붙여넣는 다는 개념으로

둘은 연결되지않은 상태로 a와 b는 독립적이다.

 

그 이해를 돕기 위해서 현재까지 순서를 다시 정리해보면

 

a = 110;

b = 20; 

 

이 상태에서 

 

b = a;로 적어주고 다시 출력해서 

 

a =110;

b= 110; 

 

이렇게 되어있는데 여기서 만약 다시 한번 b = 30; 으로 적어주고 출력해보면

 

a=110;

b=30; 

 

이렇게 출력이 되는 것이다.

 

두 숫자가 다르게 나오는 이유는 둘이 연결된 것이 아니고 단독으로 분리되어 실행되고 있기 때문에

 

a값으로 덮어쓰여진 b를 다시 30이라는 숫자로 정의해주었기 때문에 

 

30으로 출력이 되는 것이다.

 

이것이 기본자료형의 근본이다.

 

자 그럼 이번에는 참조 자료형에 대해 알아보자

 

참조자료형이란?

 

참조 자료형은 기본자료형과는 다르게 대문자로 시작하고 메서드를 가질 수 있다.

 

Camera c1 = new Camera(); 

Camera c2 = new Camera(); 

 

예를 들기위해서 c1,c2라는 객체를 새로 생성해주고 

 

c1.name = "카메라1";

c2.name = "카메라2";

 

라고 해주고 프린트로 출력해보면 

 

카메라1

카메라2 

 

라고 출력이된다.

 

그런데 만약 여기서 기본자료형처럼

 

c2 = c1; 이라고 하고 다시 출력하면 어떻게 될까?

 

동일하게 

 

카메라 1

카메라1 

 

이렇게 출력이된다. 

 

앞선 기본자료형에서는 뭐라고 설명했었나?

 

c2 = c1 이 기본자료형에서는 c1의 값을 긁어서 c2에다 덮어쓰기 한 것이라고 했고 

복사의 개념이지 둘이 묶여서 같이 움직이는 것은 아니라고 했다.

 

덮어쓰기하고 끝난 것이지 여전히 독립적이다.

 

하지만 참조자료형은

참조 말 그대로 Reference하기 때문에 

 

c2 = c1 이라는 것은 이렇게 설명할 수 있다

 

c1은 메모리 어딘가에 저장된 값을 손을 뻗어서 잡고 있다.

c2도 마찬가지로 메모리 어딘가에 저장된 값을 손을 뻗어서 꽉 잡고 있다.

 

그 상태에서 c2 = c1 이라고 선언하면

 

c1의 메모리에 값을 긁어서 c2에게 주는 것이 아니라 

 

c2는 메모리에 있는 값을 잡고 있던 손을 풀어버리고 c1이 잡고있는 값을 같이 잡는 것이다.

 

부족한 그림이지만 위 그림처럼 c1,c2가 서로 다른 풍선을 잡고있다고 가정하자

c2 = c1 이라고 하면 c2는 잡고있던 풍선을 놓아버리고 c1이 잡고있는 풍선을 같이 잡아버린다.

 

그래서 현재 값이 

 

카메라1

카메라1 

 

이렇게 나왔는데 

 

이 값은 c1의 값을 복사해서 c2에게 붙여넣기 한 것이 아니라

 

c1은 -> 카메라1 풍선을 잡고 있고 c2-> 카메라2 풍선을 잡고 있는데

 

c2가 풍선을 놓은 다음 c1이 잡고있는 카메라1풍선을 같이 잡았기 때문에

 

출력하면 

 

카메라1

카메라1 

 

이렇게 출력이 되는 것이다.

 

현 상태에서 만약 

 

 

c2.name = " 고장난 카메라 " ; 라고 정의하고

 

다시 c1,c2를 출력하면 어떻게 될까 

 

고장난카메라

고장난카메라 

 

이렇게 출력된다.

 

이상하다? 분명 기본자료형에서는 이렇게 하고 출력하면

 

카메라1

고장난카메라 

 

이렇게 나왔는데?

 

그 이유는 연결되지 않고 단독적으로 움직이는 상태에서 복사해서 단순 붙여넣기만 했기 때문에

 

하나의 값 변경이 다른 하나에게 영향을 전혀 끼치지 않기 때문이다.

 

하지만 참조자료형같은 경우는 서로 같은 풍선을 잡고있다고 앞서 설명했다.

 

그러므로 c2를 "고장난카메라" 라고 정의한다는 것은 c2는 이미 풍선을 놓치고

c1풍선을 손에 쥐고 있기 때문에 해당 풍선의 값이 바뀌는 것이다.

 

카메라1을 잡고있는 c1,c2가 있는데 그 상태에서 c2에게 "고장난카메라" 라고 정의를 해주니까

 

원래는 c2의 풍선의 값이 변경되어야 하지만 그 풍선을 이미 놓아버리고 c1의 카메라1이라는 풍선을 잡고 있으니까 

 

해당 값이 변경되어서 

 

c1,c2를 출력하면 

 

고장난카메라

고장난카메라 

 

이렇게 출력이 되는 것이다.

 

이게 바로 참조자료형의 작동원리 즉 근본이다.

 

 

또한 하단에서 이렇게 changeName이라고 메서드를 하나 만들어주고 전달값으로

Camera camera 라고 적어주자 

 

그리고 camera.name = "잘못된 카메라"; 라고 정의해주고 

 

이렇게 changeName을 호출하는데 그 값으로 c2를 넣은 다음 

c1,c2를 다시 출력하면?

 

 

이렇게 c1,c2모두 잘못된 카메라로 출력이된다.

 

그 이유는 해당 메서드에서 잘못된 카메라 라고 적어준 것을

c2에 적용하면 c2는 -> c1을 잡고 있기 때문에

결과적으로 위와 동일하게 c1을 잡고있는 해당 값을 변경시키기 때문에 

원래부터 그 값을 즉 그 풍선을 잡던 c1도 영향을 받아서

 

기본자료형처럼 분리되어 단독실행되는 것이 아니라 c1,c2 모두 영향을 받아서

 

참조자료형에 구조에 따라서 같은 값이 출력되는 것이다.

 

그런데 만약 c2가 잡고있는 c1의 풍선을 더이상 잡지 않게 하고 싶다면?

즉 연결되어있는 c1,c2를 분리시키고 싶다면? 

 

c2 = null; 이라고 적어주면 된다.

 

그렇게되면 c2는 더이상 c1의 풍선을 잡지 않고 null이라는 값을 통해서 분리되어지게 되는 것이고

다시출력해보면 Null point Exception에러가 발생하게 될 것이다.

 

 

 

이것으로 기본자료형 그리고 참조자료형이 무엇인지

 

또 어떤 차이가 있고 어떻게 사용할 수 있는지에 대해 간단하게 정리해봤다.

 

--- 예시 코드는 하단 참고 ----

 

package Practice;

import camera.Camera;

public class Reference {
    public static void main(String[] args) {
        // 참조
        // 기본 자료형 (Primitive Data Types) : int, float, double, long, boolean, ...
        int[] i = new int[3];
        System.out.println(i[0]); //0


        double[] d = new double[3];
        System.out.println(d[0]);// 0.0

        //참조 자료형 (Non-Primitive, Refernce Data Types) : String, Camera, FactoryCam, SpeedCam, ...

        String[] s = new String[3];
        System.out.println(s[0]); // null

        Camera[] c = new Camera[3];
        System.out.println(c[0] == null); // true == null


        // 기본 자료형은 메서드를 가지지 않지만 참조 자료형은 메서드를 가질 수 있다.

        // 기본 자료형은 소문자로 시작하지만 참조 자료형은 대문자로 시작한다

        //////////////////////////////////////////

        System.out.println("---------------------");

        int a =110 ;
        int b= 20;

        b = a; // 10

        System.out.println(a);
        System.out.println(b);


        System.out.println("------------------");

        b = 30;

        System.out.println(a);
        System.out.println(b);

        System.out.println("-----------------------");

        Camera c1 = new Camera();
        Camera c2 = new Camera();
        c1.name = " 카메라 1 ";
        c2.name = " 카메라 2 ";
        System.out.println(c1.name);
        System.out.println(c2.name);
        c2 = c1;
        System.out.println(c1.name);
        System.out.println(c2.name);
        c2.name = " 고장난 카메라 ";
        System.out.println(c1.name);
        System.out.println(c2.name);

        changeName(c2);
        System.out.println(c1.name);
        System.out.println(c2.name);

        c2 = null;
        System.out.println(c2.name);

        // 위와 달리 값이 둘다 들어가는 이유는
//
//        기본자료형은 값이 복사가 되는 것이고
//        참조자료형은 가리키고 있던 대상이 달라진다고 이해하면된다
//
//        기본 자료형 기준에서는
//
//        c1이 카메라
//        c2는 필름카메라 일 때
//
//        c2 = c1 이라고 해주고
//
//        c1을 출력하고
//        c2를 출력하면
//        둘다 카메라 라고 나온다 왜냐하면 c1이 카메라 니까 카메라로 출력되고
//        c2는 필름카메라니까 필름카메라로 출력되는데 아래에서 c2 = c1 이라고 해주면 기본 자료형은 복사를 해버린다
//        그러므로 복사되어서 c2도 c1처럼 카메라로 복사되어서 둘다 출력해보면 카메라,카메라가 되는 것이다.
//        만약 여기서 c2 = " 번쩍이는 비싼 카메라 " 라고 하고 다시 c1 c2 를 출력하면
//        c1은 그대로 카메라 c2만 번쩍이는 카메라라고 나온다 왜냐하면 연관되지 않고 분리되어 움직이기 때문이다
//
//        이 말은 즉 기본자료형은 c1 과 c2 는 상관이 없다 즉 연관되어 있지 않다는 것
//
//        하지만 참조 자료형은 다르다 복사가 되지 않고 가르키는 대상이 바뀌는 것이다
//        그래서 참조 자료형에서는 c1 은 카메라 c2 는 필름카메라 라고 지정하고
//        c2 = c1 이라고 해주고 출력하면 기본자료형과 다르게 c2는 원래 필름카메라를 가리키고 있는데
//        c2 = c1 이라고 해줘서 c2는 가르키던 필름카메라를 던져버리고 c1이 가리키는 카메라를 잡아버린다
//        그 상태에서 c2.name = " 디지털 카메라 " 라고 해버리면 c2 가 바뀌는 것이 아니라
//        c2가 잡고 있던 카메라를 바꿔버려서 c1 이 잡고있는 카메라가 -> 디지털 카메라가 된다 그래서 c1이 디지털 카메라를 잡고 있으니까
//        c2도 같은 걸 잡고 있어서 c1 c2 를 출력하면 둘다 디지털 카메라로 출력되는 것이다
//


    }

    public static void changeName(Camera camera){
            camera.name = "잘못된 카메라";
    }
}

 

'BackEnd' 카테고리의 다른 글

프로시저(Procedure)란 대체 무엇일까?  (0) 2023.01.25
MySQL CRUD 간단정리  (0) 2023.01.24
JAVA random 출력 예제를 통한 복습  (0) 2023.01.18
AOP란 무엇일까? 왜 사용하는 것일까?  (0) 2023.01.09
MVC 패턴  (0) 2023.01.01