ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 기본형과 참조형
    JAVA/개념 - 김영한 강의 2024. 8. 13. 23:22

     

    대원칙: 자바는 항상 변수의 값을 복사해서 대입한다. 기본형, 참조형 모두 그렇다.

     

     

    출처: https://javarevisited.blogspot.com/2015/09/difference-between-primitive-and-reference-variable-java.html

     

     

     

    기본형과 참조형?

    기본형(Primitive Type)

    • 실제 사용하는 값을 복사해서 대입
    • 변수 a자체를 b에 대입하는것이 아니다!
    int a = 10;
    int b = a;   // 모든 변수는 복사해서 대입한다.
    • int, long, double, boolean 
    • 숫자를 직접 변수에 담을 수 있으므로 변수끼리 계산이 가능하다.

     

    참조형(Reference Type)

    Studnet s1 = new Studne();
    Student s2 = s1;
    • Student student1, int[] students와 같이 데이터에 접근하기 위한 참조(위치, 주)를 저장하는 데이터.
    • 기본형이 실제 사용하는 객체를 이용한다면, 참조형은 객체의 위치를 가리키는 참조값(인스턴스의 주소)만 복사한다. 
      • 참조형에는 객체와 배열이 있다.
      • 객체는 .(dot)을 통해 메모리 상에 생성된 객체를 찾아가야 사용할 수 있다.(dot을 통해 기본형 멤버 변수에 접근하면 연산 가능) ex) d.value
      • 배열은 [ ]을 통해 메모리 상에 생성된 배열을 찾아가야 사용할 수 있다.
    •  인스턴스를 복사하는 것이 아니라, 인스턴스를 가리키는 참조값을 복사해서 전달하는 것이다. 따라서 하나의 인스턴스를 여러곳에서 참조할 수 있다. 
    • 기본형처럼 직접 계산하지 못한다. 왜? 주소만 가지고 있으니까. 
    • 참조형의 기본값은 null

     

     

     


     

    기본형 VS 참조형 변수 대입

    기본형

    VarChange1.java

    public class VarChange1 {
    
    	public static void main(String[] args) {
        	int a = 10;
            int b = a;
            System.out.println(a);  // 10
            System.out.println(b);  // 10

     

    a의 값을 복사해서 변수 b에 대입한다. 변수 a 자체를 b에 대입하는 것이 아니다.

     

          	// a 변경
            a = 20;
    	System.out.println(a);  // 20
    	System.out.println(b);  // 10

    b의 값은 변하지 않는다

     

          	// b 변경
            b = 30;
    	System.out.println(a);  // 20
    	System.out.println(b);  // 30

     

     

    참조형

    Data.java

    public class Data {
    	int value;
    }

     

    VarChange2.java

    public class VarChange2 {
     	public static void main(String[] args) {
     		Data dataA = new Data();
     		dataA.value = 10;
     		Data dataB = dataA;
     	
        	System.out.println("dataA 참조값=" + dataA);  // dataA 참조값=ref.Data@x001
     		System.out.println("dataB 참조값=" + dataB);  // dataB 참조값=ref.Data@x001
     		System.out.println(dataA.value);  // 10
     		System.out.println(dataB.value);  // 10

    참조값은 .(dot)을 통해 접근한다. Data 인스턴스를 생성 후, value 변수에 접근하여 10을 넣었다.

     

    dataA 변수는 Data 클래스를 통해 만든 참조형 변수다. 이 변수는 Data형 객체의 참조값을 저장한다. Data 객체를 생성한 뒤, 참조값을 dataA에 저장한다(x001). 그리고나서 객체 value 변수에 값 10을 저장했다. 

     

     

    변수 dataA에는 참조값 x001이 들어있다. 이 참조값을 복사해 변수 dataB에 대입한다. 인스턴스를 복사하는게 아니라 참조값만 복사해서 전달하는 것이다!(주소만 복사). 이로 인해 dataA와 dataBA의 참조값은 같아진다(x001).

     

    //dataA 변경
     dataA.value = 20;
    
     System.out.println("dataA.value = " + dataA.value);
     System.out.println("dataB.value = " + dataB.value);

     

     

    현재 dataA와 dataB의 참조값은 x001로 같다. data.value =20으로 변경하면 x001 인스턴스의 value 값이 10->20으로 변경된다. 그런데 앞서 말했듯 dataA와 dataB는 참조값이 같기 때문에 dataB.value도 20으로 변경된다.

     

     

     

     


     

    기본형과 참조형의 메서드 호출

    따라서 메서드의 호출과정도 기본형과 참조형은 상이하다. 

    기본형

      • 메서드 내부에서 매개변수(파라미터)의 값을 변경해도, 호출자의 변수 값에는 영향이 없다. 왜냐하면 값이 복사되어 전달되기 때문에 메서드 내부에서 변경된 값은 호출자의 변수와는 별개의 메모리 공간에 저장되기 때문이다.
    public class MethodChange1 {
     	public static void main(String[] args) {
        
    		 int a = 10;   // 기본형 매개변수
             
     		System.out.println("메서드 호출 전: a = " + a);  // 10
            
     			changePrimitive(a);
                
     		System.out.println("메서드 호출 후: a = " + a);  // 10
            
    	 }
     		static void changePrimitive(int x) {
     			x = 20;
     	}
    }

     

    1. int x = a;

    a=10, x=10이 된다. (x가 20인것보다 a가 x에게 10이라는 값을 전달한 게 먼저다)

     

     

    2. Primitive 메서드 안에서 x값을 변경

    a=10, x=20

     

     

     

     

    참조형

    • 메서드 내부에서 매개변수(파라미터)로 전달된 객체의 멤버 변수를 변경하면, 호출자의 객체도 변경된다. 왜냐하면 같은 객체를 가리키는 참조값이 복사되어 전달되었기 때문에, 메서드 내부에서의 변경은 호출자의 객체에도 영향을 미치기 때문이다. (같은 인스턴스를 참조하게 되니까!)

     

    ex1)

     

    Data.java

    public class Data {
     int value;
    }

     

    MethodChange2.java

    public class MethodChange2 {
     	public static void main(String[] args) {
     		Data dataA = new Data();
     		dataA.value = 10;
     
     		System.out.println("메서드 호출 전: dataA.value = " + dataA.value);  // 10
     
     		changeReference(dataA);  // int dataX = dataA
     
     		System.out.println("메서드 호출 후: dataA.value = " + dataA.value);  // 20
     		}
     
     		static void changeReference(Data dataX) {
     		dataX.value = 20;
     		}
    }

     

     

     

    1. Data 인스턴스를 생성하고 참조값을 dataA 변수에 담고 value에 숫자 10을 할당

     

     

    2. int dataX = dataA

    dataX에 dataA의 값을 전달한다.

     

    3. dataX.value = 20

    dataA, dataX 는 모두 x001 인스턴스를 참조하기 때문에 둘 다 20이라는 값을 가진다.

     

     

     

    정리

    기본형: 메서드로 기본형 데이터를 전달하면, 해당 값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수
    (파라미터)의 값을 변경해도, 호출자의 변수 값에는 영향이 없다.


    참조형: 메서드로 참조형 데이터를 전달하면, 참조값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수(파
    라미터)로 전달된 객체의 멤버 변수를 변경하면, 호출자의 객체도 변경된다.

    댓글

Designed by Tistory.