JAVA, JSP

java 5장 - 참조타입, 배열, 다차원배열, 열거

suji0730 2024. 7. 31. 14:41

 

1) 참조 타입

- 객체의 번지를 참조하는 타입

- 배열, 열거, 클래스, 인터페이스 타입 등

- 기본 타입으로 선언된 변수는 값 자체를 저장하지만, 참조 타입으로 선언된 변수는 객체가 생성된 메모리 번지를 저장, 각각 고유의 주소값을 가지고 있다.

- 기본 타입은 즉시 값을 가져올 수 있고, 참조 타입은 주소 안에 있는 값을 가져온다.

 

- 기본 타입 : 정수, 실수, 문자, 논리 값을 직접 저장(정수 : int, short, char, bype, long / 실수 : float, double / 논리 : boolean)

- 참조 타입 : 객체의 주소를 저장(배열, 열거, 클래스, 인터페이스)

 

① 배열

String[] str = new String[5];

변수타입에 [] 대입

new 연산자로 객체 생성 및 길이 지정

public static void referenceSample() {
		
    //문자열 형태의 배열을 선언, 길이는 5로 지정
    String[] arr = new String[5]; 
    arr[0] = "하이1";
    arr[1] = "하이2";
    arr[2] = "하이3";
    arr[3] = "하이4";
    arr[4] = "하이5";
    System.out.println(arr[0]);
    System.out.println(arr[1]);
    System.out.println(arr[2]);
    System.out.println(arr[3] = "수정 하이3");
    System.out.println(arr[4]);

    for(int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
}

 

1-1. 하이3 들어있는 데이터를 반복문에서 hi3으로 변경

public static void referenceSample() {
    String[] arr = new String[5]; 
    arr[0] = "하이1";
    arr[1] = "하이2";
    arr[2] = "하이3";
    arr[3] = "하이4";
    arr[4] = "하이5";
    for(int i = 0; i < arr.length; i++) {
        if(arr[i].equals("하이3")) {
            arr[i] = "hi3";
        }
        System.out.println(arr[i]);
    }
}

 

 

② 열거타입

enum color{red; green;}

public static void referenceSample() {color fc = color red;}

 

- 클래스 블록 내부에 enum 선언 / 메서드 블록 내부에 enum 객체 생성 및 변수 접근 / enum 클래스 자체 생성

- 요일, 계절처럼 한정된 값을 갖는 타입(상수)

- 열거 타입 이름은 첫 문자를 대문자로 하고 캐멀 스타일로 지어주는 것이 관례

- 메서드 영역에 저장되지만 새로운 객체 생성시 힙영역으로 저장됨

 

③ 클래스

public class ReferenceEdu{}

- 패키지 내부에 클래스 파일 생성

- 기능을 구현하기 전 설계도

 

④ 인터페이스

public interface ReferInterface{public String refer1();}

- 패키지 내부에 클래스 파일 생성시 interface 유형으로 생성

- 추상메서드만 포함하는 클래스

- 다중 상속 지원

- 다형성

- 실제 기능을 구현하기 전 메서드를 정의하는 클래스

 

 

 

1-2) 메모리 사용 영역

- JVM은 운영체제에서 할당받은 메모리 영역을 메서드 / 힙 / 스택 영역으로 구분해서 사용

 메서드 영역 : 바이트코드 파일을 읽은 내용이 저장되는 영역

                      클래스-1 (상수, 정적 필드 / 메서드 코드 / 생성자 코드 ) ... 클래스-n (상수 / 메서드 코드 / 생성자 코드)

 

② 힙 영역 : 객체가 생성되는 영역. 객체의 번지는 메서드 영역과 스택 영역의 상수와 변수에서 참조

              객체-1 / 배열-2 / 객체-3 / 배열-4 / ...

 

③ 스택 영역 : 메서드를 호출할 때마다 생성되는 프레임이 저장되는 영역

 

1-3) null

- 참조타입은 변수의 초기값을 null로 할당할 수 있다.

- 참조타입의 변수에 null을 할당하여 변수에 담긴 데이터가 없다면 스택 영역의 메모리에만 변수가 등록된다.

 

- 참조타입의 변수에 초기값을 null로 할당하고 값을 대입할 때 객체 생성

public void refer4() {
		
    //초기값 null로 할당
    int[] intArray = null;

    // 1. 첫 번째 방법
    intArray = new int[5];
    intArray[0] = 10;
    intArray[1] = 20;
    intArray[2] = 30;
    System.out.println(intArray[0]);
    System.out.println(intArray[1]);
    System.out.println(intArray[2]);

    // 2. 두 번째 방법
    intArray = new int[] {10, 20, 30};
    System.out.println(intArray[0]);
    System.out.println(intArray[1]);
    System.out.println(intArray[2]);
}

 

 

1-3) String

- String 타입의 문자열 변수는 객체를 공유하도록 설계

- 변수명이 달라도 같은 데이터라면 프로그램 상에서 같은 객체로 인식

public static void singOperatorSamle13() {
    //String 참조변수 타입 = 고유의 주소값이 부여됨.
    //서로 다른 주소값을 가진 객체가 생성돼도 데이터가 같다면 덮어씌움.
    String name1 = "홍길동";
    String name2 = "홍길동";
    System.out.println(System.identityHashCode(name1));
    System.out.println(System.identityHashCode(name2));
    boolean result1 = (name1 == name2);
    System.out.println("result : "+ result1);

    String name3 = new String("홍길동");
    String name4 = new String("홍길동");
    System.out.println(System.identityHashCode(name3));
    System.out.println(System.identityHashCode(name4));
    boolean result2 = (name3 == name4);
    System.out.println("result2 : "+ result2);

    /* == 연산자로 비교하면 메모리 주소를 비교한다.
     * java에서 문자열 리터럴은 String pool이라는 데이터 영역에 저장되는데,
     * 같은 문자열이 있는 경우 하나의 객체로 관리한다..
     * 따라서 name1, name2의 "홍길동" 문자열은 같은 객체를 참조하게 된다..
     * name1 == name2 비교연산은 메모리 상에서 같은 객체를 참조하는지 확인하므로,
     * result1의 결과가 true가 된다@!@@ 
     * 
     * result2는 String data type으로 name3, name4 객체참조변수를 선언하고,
     * new 키워드로 생성자 메서드를 호출했기 때문에 새로운 객체가 생성되는데, 이 객체는
     * 힙 메모리 영역에 할당되므로 문자열 리터럴과 다른 메모리 영역을 가진다.
     * 새로운 객체가 생성되면 새로운 주소가 생성되어서 name3 == name4 비교연산은
     * 변수의 주소를 비교하게 되고 따라서 false가 출력된다.....????
    */

    boolean result3 = (name3.equals(name4));
    System.out.println("result3 : "+ result3);

    //문자열의 데이터를 비교하려면 equals() 메서드를 사용해야 한다....
}

 

 

1-4) 문자열 관련 메서드

 

1. 특정 위치 문자 추출

public static void referenceSample2() {
    System.out.println("1. 특정위치 문자 추출");
    String name1 = "안녕하세요";
    System.out.println(name1.charAt(0));
    System.out.println(name1.charAt(1));
    System.out.println(name1.charAt(2));
    System.out.println(name1.charAt(3));
    System.out.println(name1.charAt(4));

}

 

2. 문자열 대체

public static void referenceSample3() {
    System.out.println("3. 문자열 대체");
    String name1 = "안녕하세요";
    System.out.println(name1.replace("안녕", "hi"));
}

 

3. 문자열 잘라내기

public static void referenceSample4() {
    System.out.println("4. 문자열 잘라내기");
    String name1 = "안녕하세요";

    //입력받은 자리부터 나머지 
    System.out.println(name1.substring(2));

    //입력받은 자리부터 뒷 자리까지
    System.out.println(name1.substring(2, 4));
}

 

4. 문자열 찾기

public static void referenceSample5() {
    System.out.println("5. 문자열 찾기");
    String name1 = "안녕하세요";
    System.out.println(name1.indexOf("안녕")); //일치하는 단어가 있다면 0
}

 

5. 특정 문자를 기준으로 문자열 잘라내기

public static void referenceSample6() {
    System.out.println("6. 특정 문자를 기준으로 문자열 잘라내기");
    String name1 = "안녕, 하세요";
    String[] reArr = name1.split(","); //기준이 되는 문자열은 생략됨
    System.out.println(reArr[0]);
    System.out.println(reArr[1]);
    System.out.println(reArr.length);
}

 

 

1-5) 다차원 배열

public static void referenceSample7() {
		
    //다차원 배열의 길이를 명시하여 객체 생성 = 배열에 저장되는 데이터가 없을 시
    String[][] arr = new String[2][3];
    arr[0][0] = "1번째 배열의 1번째 데이터";
    arr[0][1] = "1번째 배열의 2번째 데이터";
    arr[0][2] = "1번째 배열의 3번째 데이터";

    arr[1][0] = "2번째 배열의 1번째 데이터";
    arr[1][1] = "2번째 배열의 2번째 데이터";
    arr[1][2] = "2번째 배열의 3번째 데이터";

    System.out.println(arr[0][0]);
    System.out.println(arr[0][1]);
    System.out.println(arr[0][2]);
    System.out.println(arr[1][0]);
    System.out.println(arr[1][1]);
    System.out.println(arr[1][2]);

    //값 목록으로 다차원 배열 객체 생성 및 데이터 할당 = 배열에 저장되는 데이터가 있을 시
    String[][] arr2 = {
            {"1번째 배열의 1번째 데이터", "1번째 배열의 2번째 데이터", "1번째 배열의 3번째 데이터"},	
            {"2번째 배열의 1번째 데이터", "2번째 배열의 2번째 데이터", "2번째 배열의 3번째 데이터"}
    };
    System.out.println(arr2[0][0]);
    System.out.println(arr2[0][1]);
    System.out.println(arr2[0][2]);
    System.out.println(arr2[1][0]);
    System.out.println(arr2[1][1]);
    System.out.println(arr2[1][2]);
}

 

 

* 다차원 배열을 선언해 아래의 데이터를 할당 후 반복문을 이용해 출력
id001, pw001, 관리자, 홍01, test01
id002, pw002, 관리자2, 홍02, test02
id003, pw003, 관리자3, 홍03, test03

public static void referenceSample8() {
		
    //다차원 배열의 길이를 명시하여 객체 생성 = 배열에 저장되는 데이터가 없을 시
    String[][] arr = new String[3][5];

    arr[0][0] = "id001";
    arr[0][1] = "pw001";
    arr[0][2] = "관리자";
    arr[0][3] = "홍01";
    arr[0][4] = "test1";

    arr[1][0] = "id002";
    arr[1][1] = "pw002";
    arr[1][2] = "관리자2";
    arr[1][3] = "홍02";
    arr[1][4] = "test2";

    arr[2][0] = "id003";
    arr[2][1] = "pw003";
    arr[2][2] = "관리자3";
    arr[2][3] = "홍03";
    arr[2][4] = "test3";
    
    for(int i = 0; i < arr.length; i++) {
        for(int j = 0; j < arr[i].length; j++) {
            System.out.print(arr[i][j] + " ");
        }
        System.out.println();
    }
}

 

*p201 7.주어진 배열 항목에서 최대값,최소값을 출력하는 코드를 작성 int[] arr = {1,5,3,8,2};

public static void referenceSample11() {
    int[] arr = {1,5,3,8,2};
    int max = arr[0];
    int min = arr[0];

    for (int i = 0; i < arr.length; i++) {
        //최고점수					
        if (arr[i] > max) {
            max = arr[i];
        }
        //최저점수
        if (arr[i] < min) {
            min = arr[i];
        }
    }
    System.out.println("최고점수: " + max);
    System.out.println("최저점수: " + min);
}

 

 

* p201 8. 주어진 배열 항목의 전체 합과 평균을 구해 출력하는 코드 int[][] arr = {{95,86},{83,92,96},{78,83,93,87,88}};

public static void referenceSample11() {
    double sum = 0.0;
    double avg = 0.0;
    int cnt = 0;

    int[][] arr = {
            {95,86},	
            {83,92,96},
            {78,83,93,87,88}
    };

    for(int i=0; i < arr.length; i++) {
        for(int j=0; j < arr[i].length; j++) {
            sum += arr[i][j];
        }
        cnt += arr[i].length;
    }
    avg = (double)sum / cnt;

    System.out.println("합계: " + sum);
    System.out.println("평균점수: " + avg);
}

 

 

* p201 9.학생점수분석프로그램

public static void referenceSample9() {
    Scanner sc = new Scanner(System.in);

    boolean stu = true; //프로그램 상태를 확인하는 변수
    int studentNum = 0; //학생 수를 입력받는 변수
    int[] scores = null; //입력받은 학생수에 따라 배열길이를 지정하기 위해 초기값(null)을 할당한 배열 선언

    while(stu) {
        System.out.println("------------------");
        System.out.println("1.학생수 | 2. 점수입력 | 3. 점수리스트 | 4. 분석 | 5. 종료");
        System.out.println("선택 > ");
        int number = sc.nextInt();

        if(number==1) {
            System.out.println("학생수 > ");
            studentNum = sc.nextInt(); //학생수 입력
            scores = new int[studentNum];  //입력받은 학생수로 배열 길이 지정

        }else if(number==2) {
            for(int i = 0; i < studentNum; i++) { //입력받은 학생수의 길이만큼 반복
                System.out.print("score[" + i + "] > "); 
                scores[i] = sc.nextInt(); //입력받은 학생수의 길이만큼 점수를 입력해 배열에 데이터 할당
            }

        }else if(number==3) {
            for (int i = 0; i < studentNum; i++) { //입력받은 학생수의 길이만큼 반복
                System.out.println("scores[" + i + "]> " + scores[i]);//입력받은 점수리스트 출력
            }

        }else if(number==4) {
            if(studentNum > 0) { //학생수를 입력받았는지 검증(분석단계에서 에러가 발생할 수 있음)
                int max = scores[0]; //최고점수를 구하기 위해 입력받은 점수배열의 첫 번째 값 할당
                int min = scores[0]; //최저점수를 구하기 위해 입력받은 점수배열의 첫 번째 값 할당

                double sum = 0.0; //평균을 구하기 위해 입력받은 점수들을 더하는 변수
                double avg = 0.0; //평균값이 계산될 때 담을 수 있는 변수 선언

                for (int i = 0; i < studentNum; i++) {
                    if (scores[i] > max) { //최고점수
                        max = scores[i];
                    }
                    if (scores[i] < min) { //최저점수
                        min = scores[i];
                    }
                    sum += scores[i]; //평균점수를 내기 위해 총 점수 더하기
                }
                avg = sum / studentNum; //평균점수

                System.out.println("최고점수: " + max);
                System.out.println("최저점수: " + min);
                System.out.println("평균점수: " + avg);

            }else{
                System.out.println("학생수를 입력해주세요.");

            }
        }else if(number==5) {
            stu = false;
        }
    }
    System.out.println("프로그램 종료");
}

 

 

 

1-6) 배열 복사

1. 얕은 복사

- 배열을 그대로 복사하지만 메모리 값이 동일하다.

- 새로 담은 배열에서 데이터 수정 시 원본배열의 데이터도 변경된다.

- 주로 데이터의 수정이 이뤄지지 않고 데이터만 다른 사람들하고 공유할 때 사용된다.

 

2. 깊은 복사(권장하는 방법)

- 배열을 그대로 복사하지만 메모리 값이 동일하지 않다.

- 새로 담은 배열에서 데이터 수정 시 원본배열의 데이터도 변경되지 않는다

- 다른 사람의 코드에 영향을 미치지 않기 때문에 얼마든지 기능 구현이 가능하다.

- arraycopy()

public static void referenceSample13() {
    String[] oldArr = new String[2];
    oldArr[0] = "안녕1";
    oldArr[1] = "안녕2";

    String[] newArr = new String[5];
    System.arraycopy(oldArr, 0, newArr, 0, 2);
    // System.arraycopy(원본배열, 원본배열 복사 시작 인덱스, 새 배열, 새 배열 붙여넣기 시작 인덱스, 복사 항목 수);
    System.out.println(newArr[0]);
    System.out.println(newArr[1]);
    System.out.println(newArr[2]);
    System.out.println(newArr[3]);
    System.out.println(newArr[4]);
}

 

 

1-7) 배열 for문

public static void referenceSample14() {
    String[] arr = {"하이1", "하이2", "하이3", "하이4", "하이5", "하이6"};

    /*
    for(int i=0; i < arr.length; i++) {

        if(arr[i].equals("하이3")) {
            arr[i] = "변경";
        }
        System.out.println(arr[i]);
    }
    */

    for(String newArr : arr) {
        if(newArr.equals("하이3")) {
            newArr = "변경";
        }
        System.out.println(newArr);
    }
}

 

 

1-8) 열거(enum) 타입

public enum Week{
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURDAY, FRIDAY, STATURDAY
}

public static void referenceSample15() {
    Week today = null;
    Calendar cal = Calendar.getInstance();
    //System.out.println(cal);
    int week = cal.get(Calendar.DAY_OF_WEEK);
    System.out.println(week);

    switch(week) {
    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.THURDAY;
        break;
    case 6:
        today = Week.FRIDAY;
        break;
    case 7:
        today = Week.STATURDAY;
        break;
    }
    if(today == Week.SUNDAY) {
        System.out.println("휴식");
    }else {
        System.out.println("공부");
    }
}