본문 바로가기
Language/JAVA

[JAVA] 참조 타입 // String 배열 열거

by 아이엠제니 2021. 9. 16.

 


 

 

데이터 타입 분류

  • 기본 타입(원시 타입: primitive type)과 참조 타입(reference type)로 분류
  • 기본타입: 정수, 실수, 문자, 논리 리터럴을 저장하는 타입
  • 참조타입: 객체(Object)의 번지를 참조하는 타입. 배열, 열거, 클래스, 인터페이스 타입
  • 기본타입으로 선언된 변수와 참조 타입으로 선언된 변수의 차이점은 저장되는 값이 무엇이냐
    기본 타입으로 선언된 변수는 실제 값을 변수 안에 저장
    참조 타입으로 선언된 변수는 메모리의 번지를 값으로 갖음(번지를 통해 객체를 참조)
[기본 타입 변수]
int age = 25;
double price = 100.5;

[참조 타입 변수]
String name = "김땡땡";
String hobby = "영화감상";
  • 변수는 스택 영역에 생성, 객체는 힙 영역에 생성 - p.139

 

 


메모리 사용 영역

메소드(Method) 영역

  • JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역

 

힙(Heap) 영역

  • 객체와 배열이 생성되는 영역
  • JVM 스택 영역의 변수나 닫른 객체의 필드에서 참고

 

JVM 스택(Stack) 영역

  • 각 스레드마다 하나씩 존재하며 스레드가 시작될 때 할당
  • JVM 스택은 메소드를 호출할 때마다 프레임을 추가(push)하고 메소드가 종료되면 해당 프레임을 제거(POP)하는 동작 수행함

 

 


참조 변수의 ==, != 연산

  • 기본 타입 변수의 ==, !- 연산은 변수의 값이 같은지, 아닌지를 조사함
  • 참조 타입 변수들 간의 ==, != 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는지 알아볼 때 사용
    참조 타입 변수의 값은 힙 영역 의 객체 주소이므로 결국 주소 값을 비교
    동일한 주소 값을 갖고 있다는 것은 동일한 객체를 참조한다는 의미
    따라서 동일한 객체를 참조하고 있을 경우 == 연산의 결과는 true이고, != 연산의 결과는 false임

 

 


null과 NullPointerException

  • 참조 타입 변수는 힙 영역의 객체를 참조하지 않는다는 뜻으로 null(널) 값을 가질 수 있음
  • null 값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 생성 -p.144
  • 자바는 프로그램 실행 도중에 발생하는 오류를 예외(Exception)이라고 부름
  • 참조 변수 사용하며 가장 많이 발생하는 예외 중 하나는 NullPointerException임
    참조 타입 변수를 잘못 사용하면 발생
    참조 타입 변수가 null을 가지고 있을 경우, 참조 타입 변수는 사용할 수 없음
    변수를 추적해서 객체를 참조하도록 수정해야 함

 

 

 


String 타입

  • 문자열을 String 변수에 저장
String 변수;
변수 = "문자열"; // 큰 따옴표 감싼 문자열 리터럴을 대입
String 변수 = "문자열"; // 변수 선언과 동시에 문자열 저장

 

  • 자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 되어 있음
  • new 연산자를 사용해서 직접 String 객체를 생성시킬 수도 있음
    new 연산자는 힙 영역에 새로운 객체를 만들 때 사용하는 연ㅅ나자로 객체 생성 연산자라고 함
String name1 = new String("라라");
String name2 = new String("라라");

// name1과 name2는 서로 다른 String 객체를 참조함

 

  • 문자열 리터럴로 생성하느냐 new 연산자로 생성하느냐에 따라 비교 연산자의 결과가 달라질 수 있음
  • 동일한 문자열 리터럴로 String 객체를 생성했을 경우 ==연산의 결과는 true가 나오지만
    new 연산자로 String 객체를 생성했을 경우 ==연산의 결과는 false가 나옴
    ==연산자는 변수에 저장된 객체 번지가 동일한지를 검사하기 때문
  • 동일한 String 객체이건 다른 String 객체이건 상관없이 문자열만을 비교할 때에는
    String 객체의 equals() 메소드를 사용해야 함
  • equals() 메소드는 원본 문자열과 매개값으로 주어진 비교 문자열이 동일한지 비교한 후 true 또는 flase를 리턴함

 

// 문자열 비교

package thisisjava.chap05.num05;

public class StringEqulasExample {
    public static void main(String[] args) {
        String strVar1 = "라라";
        String strVar2 = "라라";

        if (strVar1 == strVar2) {
            System.out.println("strVar1과 strVar2는 참조가 같음");
        } else {
            System.out.println("strVa1과 strVar2는 참조가 다름");
        }

        if (strVar1.equals(strVar2)) {
            System.out.println("strVar1과 strVar2는 문자열이 같음");
        }

        String strVar3 = new String("라라");
        String strVar4 = new String("라라");

        if (strVar3 == strVar4) {
            System.out.println("strVar3과 strVar4는 참조가 같음");
        } else {
            System.out.println("strVar3과 strVar4는 참조가 다름");
        }

        if (strVar3.equals(strVar4)) {
            System.out.println("strVar3과 strVar4는 문자열이 같음");
        }
    }
}

 

 

 


배열 타입

배열

  • 같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스(inderx)를 부여해 놓은 자료구조
  • 배열은 같은 타입의 데이터만 저장할 수 있음
    int 배열은 int 값만, String 배열은 문자열만 저장 가능
  • 배열은 선언과 동시에 저장할 수 있는 데이터 타입이 결정
  • 한 번 생성된 배열은 길이를 늘리거나 줄일 수 없음

 

 

배열 선언

타입 [] 변수;
타입 변수[];
  • 배열 변수는 참조 변수에 속함
  • 배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체를 참조하게 됨
    참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있음
타입[] 변수 = null;

 

 

값 목록으로 배열 생성

  • 배열 항목에 저장될 값의 목록이 있다면, 다음과 같이 간단하게 배열 객체를 만들 수 있음
데이터타입[] 변수 = { 값0, 값1, 값2, 값3, ... };

String[] names = { "똘기", "떵이", "호치", "새초미", ...};
  • 중괄호 {}는 주어진 값들을 항목으로 가지는 배열 객체를 힙에 생성. 배열 객체의 번지를 리턴함

 

// 값 목록으로 배열 생성

package thisisjava.chap05.num06;

public class ArrayCreateByValueListExample {
    public static void main(String[] args) {
        int[] scores = {83, 90, 87};

        System.out.println("scores[0] : " + scores[0]);
        System.out.println("scores[1] : " + scores[1]);
        System.out.println("scores[2] : " + scores[2]);

        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += scores[i];
        }
        System.out.println("총합: " + sum);
        double avg = (double) sum / 3;
        System.out.println("평균: " + avg);
    }
}

  • 배열 변수를 이미 선언한 후에 다른 실행문에서 중괄호를 사용한 배열 생성은 허용되지 않음

 

// 값의 리스트로 배열 생성

package thisisjava.chap05.num06;

public class ArrayCreateByValueListExample2 {
    public static void main(String[] args) {
        int[] scores;
        scores = new int[]{83, 90, 87};
        int sum1 = 0;
        for (int i = 0; i < 3; i++) {
            sum1 += scores[i];
        }
        System.out.println("총합: " + sum1);

        int sum2 = add(new int[]{83, 90, 87});
        System.out.println("총합: " + sum2);
        System.out.println();
    }

    public static int add(int[] scores) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {
            sum += scores[i];
        }
        return sum;
    }
}

 

 

new 연산자로 배열 생성

  • 값의 목록을 가지고 있지 않지만, 향후 값들을 저장할 배열을 미리 만들고 싶다면 new 연산자로 다음과 같이 배열 객체를 생성시킬 수 있음
타입[] 변수 = new  타입[길이]; //길이는 배열이 저장할 수 있는 값의 수를 말함
  • new 연산자로 배열을 생성할 경우에는 이미 배열 변수가 선언된 후에도 가능
  • new 연산자로 배열을 처음 생성할 경우, 배열은 자동적으로 기본값으로 초기화됨
// new 연산자로 배열 생성

package thisisjava.chap05.num06;

public class ArrayCreateByNewExample {
    public static void main(String[] args) {
        int[] arr1 = new int[3];
        for (int i = 0; i < 3; i++) {
            System.out.println("arr1[" + i + "] : " + arr1[i]);
        }
        arr1[0] = 10;
        arr1[1] = 20;
        arr1[2] = 30;
        for (int i = 0; i < 3; i++) {
            System.out.println("arr1[" + i + "] : " + arr1[i]);
        }

        double[] arr2 = new double[3];
        for (int i = 0; i < 3; i++) {
            System.out.println("arr2[" + i + "] : " + arr2[i]);
        }
        arr2[0] = 0.1;
        arr2[1] = 0.2;
        arr2[2] = 0.3;
        for (int i = 0; i < 3; i++) {
            System.out.println("arr2[" + i + "] : " + arr2[i]);
        }
        String[] arr3 = new String[3];
        for (int i = 0; i < 3; i++) {
            System.out.println("arr3[" + i + "] : " + arr3[i]);
        }
        arr3[0] = "1월";
        arr3[1] = "2월";
        arr3[2] = "3월";
        for (int i = 0; i < 3; i++) {
            System.out.println("arr3[" + i + "] : " + arr3[i]);
        }
    }
}

 

 

배열 길이

  • 배열에 저장할 수 있는 전체 항목 수를 말함
  • 배열 객체의 length 필드를 읽으면 됨
    참고로 필드는 객체 내부의 데이터를 말함
  • 배열의 length 필드를 읽기 위해서는 배열 변수에 도트(.) 연산자를 붙이고 length를 적어주면 됨
배열변수.length;

 

// 배열 length 필드

package thisisjava.chap05.num06;

public class ArrayLengthExample {
    public static void main(String[] args) {
        int[] scores = {83, 90, 87};

        int sum = 0;
        for (int i = 0; i < scores.length; i++) {
            sum += scores[i];
        }
        System.out.println("총합: " + sum);

        double avg = (double) sum / scores.length;
        System.out.println("평균: " + avg);
    }
}

  • 배열의 인덱스 범위는 0~(길이-1)임

 

 

커맨드 라인 입력

//main() 메소드의 매개 변수

package thisisjava.chap05.num06;

public class MainStringArrayArgument {
    public static void main(String[] args) {
        if (args.length != 2) {
            System.out.println("프로그램의 사용법");
            System.out.println("java MainStringArrayArgument num1 num2");
            System.exit(0);
        }
        String strNum1 = args[0];
        String strNum2 = args[1];

        int num1 = Integer.parseInt(strNum1);
        int num2 = Integer.parseInt(strNum2);

        int result = num1 + num2;
        System.out.println(num1 + " + " + num2 + " = " + result);
    }
}

 

 

다차원 배열

  • 행과 열로서 구성된 배열을 2차원 배열이라고 함
    가로 인덱스와 세로 인덱스를 사용함
    자바는 2차원 배열을 중첩 배열 방식으로 구현
  • 2(행) x 3(열) 행렬을 만들기 위해 다음과 같은 코드 사용
int[][] scores = new int[2][3];

 

// 배열 속의 배열

package thisisjava.chap05.num06;

public class ArrayInArrayExample {
    public static void main(String[] args) {

        int[][] mathScores = new int[2][3];
        for (int i = 0; i < mathScores.length; i++) {
            for (int k = 0; k < mathScores[i].length; k++) {
                System.out.println("mathScores[" + i + "][" + k + "]=" + mathScores[i][k]);
            }
        }
        System.out.println();

        int[][] englishScores = new int[2][];
        englishScores[0] = new int[2];
        englishScores[1] = new int[3];
        for (int i = 0; i < englishScores.length; i++) {
            for (int k = 0; k < englishScores[i].length; k++) {
                System.out.println("englishScores[" + i + "][" + k + "]=" + englishScores[i][k]);
            }
        }
        System.out.println();

        int[][] javaScores = {{95, 80}, {92, 96, 80}};
        for (int i = 0; i < javaScores.length; i++) {
            for (int k = 0; k < javaScores[i].length; k++) {
                System.out.println("javaScores[" + i + "][" + k + "]=" + javaScores[i][k]);
            }
        }
    }
}

 

 

객체를 참조하는 배열

  • String[] 배열 항목 간에 문자열을 비교하기 위해서는 ==연산자 대신 equals() 메소드를 사용
  • ==는 객체의 번지 비교이기 때문에 문자열 비교에 사용할 수 없음
// 객체를 참조하는 배열

package thisisjava.chap05.num06;

public class ArrayReferenceObjectExample {
    public static void main(String[] args) {
        String[] strArray = new String[3];
        strArray[0] = "Java";
        strArray[1] = "Java";
        strArray[2] = new String("Java");
        System.out.println(strArray[0] == strArray[1]);
        System.out.println(strArray[0] == strArray[2]);
        System.out.println(strArray[0].equals(strArray[2]));
    }
}

 

 

배열 복사

  • 배열 간의 항목 값들을 복사하려면 for문을 사용하거나 System.arraycopy() 메소드를 사용하면 됨
// for문으로 배열 복사

package thisisjava.chap05.num06;

public class ArrayCopyByForExample {
    public static void main(String[] args) {
        int[] oldIntArray = {1, 2, 3};
        int[] newIntArray = new int[5];

        for (int i = 0; i < oldIntArray.length; i++) {
            newIntArray[i] = oldIntArray[i];
        }

        for (int i = 0; i < newIntArray.length; i++) {
            System.out.print(newIntArray[i] + ", ");
        }
    }
}

> 1,2,3 복사 / 복사되지 않은 항목은 int[] 배열의 기본 초기값 0이 그대로 유지

 

  • 참조 타입 배열일 경우, 배열 복사가 되면 복사되는 값이 객체의 번지
    새 배열의 항목은 이전 배열의 항목이 참조하는 개체와 동일, 이것은 얕은 복사(shallow copy)
  • 깊은 복사(deep copy)는 참조하는 객체도 별도로 생성하는 것을 말함

 

 

향상된 for문

 

  • 반복 실행을 하기 위해 카운터 변수와 증감식을 사용하지 않음
  • 배열 및 컬렉션 항목의 개수만큼 반복하고, 자동적으로  for문을 빠져나감
for(타입 변수 : 배열 {
  실행문;
}

 

// 향상된 for문

package thisisjava.chap05.num06;

public class AdvancedForExample {
    public static void main(String[] args) {
        int[] scores = {95, 71, 84, 93, 87};

        int sum = 0;
        for (int score : scores) {
            sum = sum + score;
        }
        System.out.println("점수 총합 = " + sum);

        double avg = (double) sum / scores.length;
        System.out.println("점수 평균 = " + avg);
    }
}

 

 

 


열거 타입

  • 한정된 값만을 갖는 데이터 타입이 열거 타입임
  • 몇 개의 열거 상수 중에서 하나의 상수를 저장하는 데이터 타입

 

 

열거 타입 선언

  • 열거 타입의 이름을 정함
  • 열거 타입 이름으로 소스 파일(.java)을 생성
  • 열거 타입 이름은 관례적으로 첫 문자를 대문자로 함. 나머지는 소문자로 구성
    여러 단어로 구성된 이름이라면 단어 첫 문자는 대문자로 하는 것이 관례
Week.java
MemberGrade.java
  • public enum 키워드는 열거 타입을 선언하기 위한 키워드. 반드시 소문자 작성
  • 열거 타입 이름은 소스 파일명과 대소문자가 모두 일치해야 함
public enum 열거타입이름 {...}
  • 열거 상수는 모두 대문자로 작성
  • 열거 상수가 여러 단어로 구성될 경우에는 단어 사이를 밑줄(_)로 연결하는 것이 관례
public enum LoginResult {LOGIN_SUCCESS, LOGIN_FAILED}

 

// 열거 타입 선언

package thisisjava.chap05.num07;

public enum Week {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

 

 

열거 타입 변수

  • 열거 타입도 하나의 데이터 타입이므로 변수를 선언하고 사용해야 함
열거타입 변수;

열거타입 변수 = 열거타입.열거상수;
Week today = Week.SUNDAY;

 

// 여거 타입과 열거 상수

package thisisjava.chap05.num07;

import java.util.Calendar;

public class EnumWeekExample {
    public static void main(String[] args) {
        Week today = null;

        Calendar cal = Calendar.getInstance();
        int week = cal.get(Calendar.DAY_OF_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.THURSDAY;
                break;
            case 6:
                today = Week.FRIDAY;
                break;
            case 7:
                today = Week.SATURDAY;
                break;
        }
        System.out.println("오늘 요일: " + today);

        if (today == Week.SUNDAY) {
            System.out.println("일요일에는 축구를 합니다");
        } else {
            System.out.println("열심히 자바 공부합니다");
        }
    }
}

 

 

열거 객체의 메소드 - p.176

리턴 타입 메소드(매개 변수) 설명
String name() 열거 객체의 문자열을 리턴
int ordinal() 열거 객체의 순번(0부터 시작)을 리턴
int compareTo() 열거 객체를 비교해서 순번 차이를 리턴
열거 타입 valueOf(String name) 주어진 문자열의 열거 객체를 리턴
열거 배열 values() 모든 열거 객체들을 배열로 리턴

 

// 열거 객체의 메소드

package thisisjava.chap05.num07;

public class EnumMethodExample {
    public static void main(String[] args) {
        //name() 메소드
        Week today = Week.SUNDAY;
        String name = today.name();
        System.out.println(name);

        //ordinal() 메소드
        int ordinal = today.ordinal();
        System.out.println(ordinal);

        //compartTo() 메소드
        Week day1 = Week.MONDAY;
        Week day2 = Week.WEDNESDAY;
        int result1 = day1.compareTo(day2);
        int reuslt2 = day2.compareTo(day1);
        System.out.println(result1);
        System.out.println(reuslt2);

        //valueOf(메소드)
        if (args.length == 1) {
            String strDay = args[0];
            Week weekDay = Week.valueOf(strDay);
            if (weekDay == Week.SATURDAY || weekDay == Week.SUNDAY) {
                System.out.println("주말이군요");
            } else {
                System.out.println("평일이군요");
            }
        }

        //values() 메소드
        Week[] days = Week.values();
        for (Week day : days) {
            System.out.println(day);
        }
    }
}

 

 

 

'이것이 자바다' 공부 기록
300x250