본문 바로가기

Programming/자바

자바 재정리 - 참조

참조

: 값이 직접 할당되지 않고 값이 있는 주소를 가리키는 것

ex. 배열 타입, 열거 타입, 클래스(ex. String), 인터페이스
=> 참조 객체 자체는 힙 영역, 객체의 주소값은 스택 영역에 생성됨

 

 

※ 데이터 타입

 

 

 

※ 메모리 구조

1. 메소드 영역 (=클래스/정적 영역)
전역변수, 정적 멤버변수 저장
메인 메소드의 클래스, 정적변수(=> 바이트 코드)가 로드됨 -> JVM이 메인메소드 호출 가능해짐

2. 스택 영역 => 공유되는 다른 영역과 달리 스레드별로 각각 생성됨
지역변수, 매개변수 저장
기본형 변수(공간에 직접 할당되는 값들 ex.int), 참조값의 주소 저장
메소드 호출 될때마다 지역변수 저장, 호출 끝나면 저장됐던 변수들 제거됨

3. 힙 영역
참조값 저장
인스턴스 변수(new로 생성) 저장
변수 제거되지 않음 (JVM 가비지 컬렉터가 삭제하거나 JVM 종료되기 전까지)

 

 

 

  •  String 타입

문자열은 직접 변수에 저장되지 않음

=> 문자열은 힙영역에서 String 객체로 생성되며, 변수는 스택영역에서 String 객체를 참조함

 

 

  • 참조 주소값, 문자열 리터럴(내용) 비교 ( ==, equals() )
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
public static void main(String[] args) {
    String str1= "김철수";
    String str2= "김철수";
    if (str1==str2) { //문자열 리터럴이 같으면 같은 객체 참조
        System.out.println("str1과 str2는 참조가 같음");
    } else {
        System.out.println("str1과 str2는 참조가 다름");
    }
    if (str1.equals(str2)) {
        System.out.println("같은 문자열임");
    } else {
        System.out.println("다른 문자열임");
    }
 
    String str3 = new String("김철수");
    String str4 = new String("김철수"); //new => 또다른 새로운 객체
    if (str3==str4) {  //참조 비교 (=> 객체 주소번지 비교)
        System.out.println("str1과 str2는 참조가 같음");
    } else {
        System.out.println("str1과 str2는 참조가 다름");
    }
    if (str3.equals(str4)) {  //값 내용 비교
        System.out.println("같은 문자열임");
    } else {
        System.out.println("다른 문자열임");
    }
}
//
str1과 str2는 참조가 같음
같은 문자열임
str3과 str4는 참조가 다름
같은 문자열임
cs

 

 

 

  • 배열 타입

: 같은 타입의 데이터들을 연속된 공간에 나열하고, 인덱스 부여한 자료구조

 

 

  • 배열 선언

int[] Array;

int Array[];

 

 

  • 초기화

int[] Array = null;

 

=> 참조할 배열 객체 없을 때 null 값으로 초기화

 

 

  • 배열 생성

1. 값 목록으로 배열 생성

 
public static void main(String[] args) {
int[] scores = {78,96,80,63,86};   
        for (int i=0;i<scores.length;i++) {
            System.out.println(scores[i]);
        }
    }

//
78
96
80
63
86

 

2. new 연산자로 배열 생성

int[] scores = new int[5];    //값 5개 있는 배열 생성  //기본값으로 초기화됨 (int: 0, String: null, boolean: false)
for (int i=0;i<scores.length;i++) {  //배열의 길이
  System.out.println(scores[i]);
}

//
0
0
0
0
0

 

 

  • 다차원 배열

: 행, 열로 구성된 배열 (가로, 세로 인덱스)

 

 

    1행 (0 0 0) => 주소 a

    2행 (0 0 0) => 주소 b

=> 각 행마다 다른 주소번지 가리킴 (=참조값)

 

 

int[][] nums = new int[2][3];    //2행 3열

 

int[][] nums2 = new int[2][]; //행 2개 생성

nums2[0]=new int [3];  //[0]행에 값 3개 할당  (0 0 0)

nums2[1]=new int [4];  //[1]행에 값 4개 할당  (0 0 0 0)

=>

nums2.length : 2  //행 갯수

nums2[0].length : 3  //[0]행의 열 갯수

nums2[0].length : 4  //[1]행의 열 갯수

 

 

    public static void main(String[] args) {
        int[][] nums = new int[2][3];
        nums[0][0]=10//(0,0)에 10 할당
        nums[1][1]=50//(1,1)에 50 할당
        System.out.println(nums.length);    //2 (행 수)  //각 행마다 하나의 주소번지 가리킴 
        System.out.println(nums[0].length);     //3 (열 수) //0번째 주소번지가 갖고 있는 칸들 
    
        for (int a=0;a<nums.length;a++) {
            for(int b=0;b<nums[a].length;b++) {
                System.out.print(nums[a][b]+" ");  //10 0 0 0 50 0 
            }
        }
    }

 

 

※ 배열 인덱스 오류
int[] nums= new int[5];    //크기, 갯수가 5
nums[0]=10;
nums[5]=50;    //인덱스는 0~4까지만 존재 => 5는 존재X

 

 

  • 배열 복사

 

- 틀린 예시

public static void main(String[] args) {
int[] nums1 = {10,20,30,40,50}; //nums1, 즉 배열 자체는 주소번지로 이뤄진 참조타입
int[] nums2 = new int[5]; //배열 선언 : 0으로 채워짐
nums2=nums1;   //nums2는 nums1이 가리키는 주소 똑같이 가리킴
System.out.println(nums2[2]); 
}

//30

=> 값이 아닌 주소값(참조값) 복사한 것

 

 

- 옳은 예시

public static void main(String[] args) {
int[] nums1 = {10,20,30};
int[] nums2 = new int[5];
for (int i=0;i<nums1.length;i++) {
nums2[i]=nums1[i];    //참조값이 아닌 값의 내용 가져옴
}
for (int i=0; i<nums2.length;i++) {
System.out.print(nums2[i]+" ");
}
}
//
10 20 30 0 0 

 

 

- 옳은 예시 - Arraycopy 메소드 사용

public static void main(String[] args) {
int[] nums1 = {10,20,30};
int[] nums2 = new int[5];
System.arraycopy(nums1, 0, nums2, 0, nums1.length);    
//nums1[0]부터 복사 -> nums2[0]으로 3개 붙여넣기
for (int i=0; i<nums2.length;i++) {
System.out.print(nums2[i]+" ");
}
}
//
10 20 30 0 0 

 

 

- 참조타입 배열 복사 => 얕은 복사 (원본 or 복사본 연동됨)

ex. 

public static void main(String[] args) {
String[] str1 = {"김철수","이영희","홍길동"};
String[] str2 = new String[5];

System.arraycopy(str1, 0, str2, 0, str1.length);

//참조의 참조


for (int i=0; i<str2.length;i++) {
System.out.print(str2[i]+" ");
}
}
//
김철수 이영희 홍길동 null null 

 

 

  • 향상된 for문

for(타입 변수 : 배열이름) {
  반복할 내용
}

 

ex.

public static void main(String[] args) {
        int[] scores = {78,80,90,75,60};
        int sum=0;
        double avg;
        for (int score:scores) {
            sum+=score;
        }
        avg=(double)sum/scores.length;
        System.out.println("총점 : "+sum);
        System.out.println("평균 : "+avg);
}

//
총점 : 383
평균 : 76.6

 

 

 

  • 열거 타입

: 하나의 열거 타입 내에서 고정값들(열거 상수) 열거됨

ex. 요일 => 월,화,수,목,금,토,일

 

열거 상수는 대문자로 작성

 

 

  • 열거타입 선언

1. 소스파일 생성

Week.java

 

2. 소스 파일 내 열거타입 및 열거상수 선언

public enum Week {  //열거 타입

MON,  //열거 상수

TUES,

WED, ~~

}

 

 

  • 열거타입 활용
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
import java.util.Calendar;
 
public class EnumWeekEx1 {
 
    public static void main(String[] args) {
        Week today = null;
        Calendar cal = Calendar.getInstance();  
        int w=cal.get(Calendar.DAY_OF_WEEK);  //요일을 수로 환산 (1: 일요일)
        switch(w) {
            case 1:
                today=Week.SUNDAY;
                break;
            case 2:
                today=Week.MONDAY;
                break;
            case 3:
                today=Week.TUESDAY;
                break;
            case 4:
                today=Week.WEDNESDAY;
                break;
            case 5:
                today=Week.THURSDAY;
                break;
            case 6:
                today=Week.FRIDAY;
                break;
            case 7:
                today=Week.SUNDAY;
                break;
        }
        System.out.println(today);
        if (today==Week.SUNDAY) {
            System.out.println("일요일이니 집에서 쉬세요.");
        }else {
            System.out.println("열심히 자바 공부합시다.");
        }
 
    }
 
}
cs

 

 

  • 열거객체 메소드

name() : 열거객체 문자열 리턴 (SUNDAY)

ordinal() : 열거객체 순번 리턴 (6)

compareTo() : 열거 객체 간 순번 차이 비교 ex. day1.compareTo(day2)

valueOf() : 주어진 문자열의 열거객체 리턴 ex. Week.valueOf('SAT)

values() : 모든 열거객체들 배열로 리턴  ex. Week.values()

 

 

 

 

참고:

https://coding-factory.tistory.com/830

 

[Java] 메모리 구조 메소드(Method), 스택(Stack), 힙(Heap) 영역에 대하여

자바뿐만이 아니라 모든 프로그램이 구동되기 위해서는 프로그램 구동시에 운영체제로부터 메모리(RAM) 공간을 할당받아야 합니다. 이러한 메모리는 무제한이 아니라 한정되어 있습니다. 그렇

coding-factory.tistory.com

https://pearlluck.tistory.com/10

 

메모리구조 : 메소드, 힙, 스택

정리 JVM이 메모리를 OS에게 요청하면 OS는 메모리를 할당한다. 이때 받은 메모리를 클래스영역,스택영역,힙영역으로 메모리 구조를 나눌 수 있다. ​ 클래스 영역은 프로그램이 실행하기 위해 바

pearlluck.tistory.com

https://kingpodo.tistory.com/54

 

Java의 데이터 타입의 분류(기본 타입, 참조 타입)와 메모리 영역

1. Java 데이터 타입의 분류 프로그램은 자료구조(데이터)와 알고리즘의 결합으로 이루어집니다. 즉 프로그램이란 자료구조를 통해 데이터를 구성하고 표현하며 알고리즘을 통해 문제를 해결합

kingpodo.tistory.com

https://velog.io/@mmy789/Java-%EC%B0%B8%EC%A1%B0-%ED%83%80%EC%9E%85-2

 

'Programming > 자바' 카테고리의 다른 글

자바 재정리 - 상속  (0) 2022.08.23
자바 재정리 - 클래스  (0) 2022.08.11
생활코딩 자바 - Collections framework  (0) 2022.04.24
생활코딩 자바 - 제네릭  (0) 2022.04.20
생활코딩 자바 - 참조 ?  (0) 2022.04.19