210101 이것이 자바다 5장

송은석·2021년 1월 1일
0
post-thumbnail

신용권 님의 ''이것이 자바다'' 5장 공부 기록

책을 보면서 새롭게 눈에 들어온 부분만 담았다. 이전에 배운 부분이기도 하고, 비교적 간단한 내용을 다루고 있기 때문이다.


5. 참조 타입

5.1 데이터 타입 분류

  • 데이터 타입에는 기본 타입과 참조 타입이 있다.

  • 둘의 차이는 변수에 저장되는 값이 다르다는 것이다. 기본 타입은 실제 값을 변수 안에 저장하고, 참조 타입은 메모리의 번지를 값으로 가진다. 이렇게 번지를 통해 객체를 참조한다는 뜻에서 참조타입이라고 한다.

  • 변수는 스택 영역에, 객체는 힙 영역에 저장된다.


5.2 메모리 사용 영역

  • JVM은 메모리 영역(Runtime Data Area)를 메소드, 힙, 스레드 영역으로 나누었다.

  • 메소드 영역에는 클래스, 필드, 런타임 상수풀 등이 저장된다. JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역이다.

  • 힙 영역객체와 배열이 생성되는 영역이며, 생성된 객체와 배열은 스택 영역의 변수나 다른 객체의 필드에서 참조한다. 참조하는 변수나 필드가 없다면 쓰레기 객체로 간주되어 쓰레기 수집기에 의해 제거된다.

  • 스레드 영역은 .. 솔직히 아직 이해 못했다. 스택의 영역을 말하는 것 같은데, main스레드와 같은 말로 대강 이해했다. 프로그램이 실행되는 영역으로 생각하고 있다.


5.3 참조변수의 ==. != 연산

  • 참조변수는 ==, != 연산으로 객체의 주소를 비교할 수 있다.

5.4 null과 NullPointerException

  • 참조변수는 힙 영역의 객체 참조를 하지 않는다는 뜻으로 null값을 가지며, null로 초기화된 참조 변수는 스택 영역에 생성된다.
  • NullPointerException : null 값으로 인한 예외상황이 발생할 수 있다. 참조 타입 변수가 null을 가지고 있는데, 이 변수를 사용하려 할 때 발생한다. null은 참조할 객체가 없기 때문이다.

5.5 String 타입

  • String 객체로 문자열을 생성하고 변수는 String 객체를 참조한다.
  • 문자열 리터럴이 동일하면 String 객체를 공유하게 된다. 그러나 new 연산자를 사용하면, 힙 영역에 새로운 String 객체를 생성할 수도 있다. 따라서 문자열을 비교할 때는 "=="이나 "!="가 아닌 ".equals()" 메소드를 사용해야 한다.
String a = "어떻게";
String b = "어떻게";
String c = new String("어떻게");

System.out.println(a==b);//true
System.out.println(a==c);//false
System.out.println(a.equals(c));//true
  • String 변수는 참조 변수이므로 null값을 대입할 수도 있다. 그러면 객체는 쓰레기 객체가 되고, 쓰레기 수집기에 의해 메모리에서 제거된다. 다시 해당 변수를 사용하고 싶다면, new 연산자를 사용하여 새로운 객체를 생성해야 한다.

5.6 배열 타입

  • 배열이란, 같은 타입의 데이터를 연속된 공간에 나열시키고, 각 데이터에 인덱스(index)를 부여해 놓은 자료구조이다.

  • 만약, 다른 타입의 데이터를 저장하려고 하면 타입 불일치(Type mismatch) 컴파일 오류가 발생한다.

  • 생성된 배열의 타입과 길이는 바꿀 수 없다.

5.6.1 배열 선언

  • 타입 [] 변수; 혹은 타입 변수 []; 의 형태를 가진다. ex) int [] arr; , int arr [];

  • 이 때 배열은 참조변수에 속하므로 참조할 배열 객체가 없으면 배열 변수들을 null 값으로 초기화 된다. 이 변수를 읽거나 저장하려 하면 앞에서 언급했던 NullPointerException이 발생한다. 배열을 생성하고 참조하는 상태에서 값을 저장하거나 읽어야 한다.

5.6.2 값 목록으로 배열 생성

  • 타입 [] 변수 = {값1, 값2, 값3}; 의 형태를 가진다. ex) int [] arr = {1, 3, 5 };

  • 중괄호로 주어진 값들을 항목으로 가지는 배열 객체를 힙 영역에 생성하고 배열 객체의 번지를 리턴한다.

  • 한편, 선언 후(타입 변수 [];)에는 중괄호를 사용한 배열 생성이 불가하다. 그러나 new연산자를 사용하면 가능하다.

    -> 타입 [] 변수; //원래는 중괄호 사용 불가 but

    ​ 변수 = new 타입[] {값1, 값2, 값3};

  • 메소드의 매개값으로 값 목록이 없는 배열이 사용될 경우에도 new 연산자와 중괄호를 사용하면 매개값으로 사용이 가능해진다.

int result = add( {100, 39, 40});//컴파일 에러
int result = add( new int[]{100, 39, 40}); //가능

5.6.3 new 연산자로 배열 생성

  • 값의 목록이 없지만 향후 값들을 저장할 배열을 미리 만들고 싶다면 new 연산자를 활용하면 된다.

  • 값 목록 없는 배열 크기 설정

    -> 타입 변수 [] = new 타입[길이]; ex) int arr [] = new int [3];

  • 그리고 new로 배열을 생성하면 자동 초기화가 되어 초기값이 null값이 된다.

  • 배열 길이를 얻을 때는 length필드(객체 내부의 데이터)를 읽으면 된다. 이는 for문에 많이 쓰이며, 인덱스를 초과하여 사용할 경우에는 ArrayIndexOutOfBoundsException이 발생하게 된다.

5.6.4 커맨드 라인 입력

  • main 메소드 옆에는 왜 String [] args가 매개값으로 쓰여 있을까?
  • 먼저 "java 클래스"로 프로그램을 실행하면 jvm은 길이가 0인 String 배열을 먼저 생성하고, main 메소드 호출시 매개값으로 전달한다. 이렇게 메인 메소드는 args의 길이와 데이터를 받아 사용할 수 있게 된다.
  • 이클립스에서는 run -> run configuration에서, cmd에서는 "java MainStringArrayArgument 변수1 변수2... "의 방식으로 입력가능하다.
  • 이렇게 입력된 문자열은 Integer.parseInt() 메소드를 통해 정수로 변환하여 사용할 수 있다. 이 때 정수 변환 불가 문자열이 입력될 경우에는 NumberFormatException이 발생하게 된다.

5.6.5 다차원 배열

  • 배열은 다차원으로 사용이 가능하다. 이는 행렬의 모습과 비슷한데. 자바는 이를 중첩 배열의 형식으로 구현한다.
  • 그러므로 일차원 배열이 서로 연결된 구조로 다차원 배열을 구현하게 되므로 수학 행렬 구조가 아닌 계단식 구조를 가지게 된다.
  • 이렇ㄴ 형태의 배열에서는 반드시 정확한 배열의 길이를 알고 인덱스를 사용해야 하며 그렇지 않을 경우 ArrayIndexOutOfBoundsException이 발생한다.

5.6.6 객체를 참조하는 배열

  • 기본 타입 배열은 각 항목에 직접 값을 가지고 있으나, 참조 타입 배열은 각 항목에 객체의 번지를 가지고 있다.
  • 따라서 String 배열의 항목은 String 변수처럼 ".equals()"를 사용하여 비교해야 한다.
  • 동일한 문자열은 같은 객체를 참조하지만, new 연산자로 새로운 객체를 생성 시 새로운 객체를 참조하게 되기 때문이다.

5.6.7 배열 복사

  • 배열은 한 번 생성 후 크기 변경을 할 수 없으므로 더 많은 저장 공간이 필요하다면 보다 큰 배열을 만들고 이전 배열로 부터 항목 값들을 복사해야 한다.

  • 이 때 두 가지의 방식을 사용할 수 있다.

    1. for문 사용
  int [] oldArray = {1,3,4};
  int [] newArray = new int [5];
  
  for(int i=0; i<oldArray.length; i++){
      newArray[i] = oldArray[i];
  }
  1. System.arraycopy() 메소드 사용
  int [] oldArray = {1,3,4};
  int [] newArray = newArray int [5];
  
  System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
  //매개 값 : 원본배열, 원본 복사 시작인덱스, 새 배열, 새 배열 붙여넣을 시작인덱스, 복사할 개수

5.6.8 향상된 for문

  • 배열과 컬렉션 객체를 좀 더 쉽게 처리하기 위해 개발된 for문
  • 반복실행을 하기 위해 카운터 변수와 증감식을 사용하지 않는다. 배열 및 컬렉션 항목의 개수만큼 반복하고, 자동으로 for문을 나간다.
for(타입변수 : 배열 ){
    실행문
} //향상된 for문 예시

5.7 열거 타입

  • 열거 타입(enumeration constant)은 요일, 계절 등 한정된 값만을 가지는 데이터 타입이다. 또한 몇개의 열거 상수(enumeration constant) 중에서 하나의 상수를 저장하는 데이터 타입이다.

5.7.1 선언

  • 열거 타입의 이름을 정하고, 소스 파일(.java)을 생성한다. 열거 타입이름은 첫 문자를 대문자로 한다. 또한 열거 상수는 모두 대문자로 작성한다.
//Week.java
public enum Week{ //열거타입 이름
    MONDAY, TUESDAY, WENESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY //열거상수
}

5.7.2 열거 타입 변수

  • 열거 타입 변수를 선언했다면 열거 상수를 저장할 수 있다. 열거 상수는 단독으로 사용할 수 없으며 반드시 열거타입.열거상수로 사용된다.
//열거타입 변수 = 열거타입.열거상수;
Week today = Week.SUNDAY;
//이는 메소드 영역의 참조번지 주소를 스택의 변수영역에 복사한 것과 같다.
//그러므로 이 둘은 같은 객체를 참고하게 되고, ==연산의 결과가 참으로 나오게 된다.

Week birthday = null; // 열거 타입 변수도 참조타입이므로 열거 상수는 객체이고, 따라서 null값을 저장할 수 있다.

5.7.3 열거 객체의 메소드

  • 열거 객체의 메소드는 java.lang.Enum 클래스에 선언된 메소드이며, 컴파일 시 Enum 클래스를 상속한다.
  1. name() 메소드

    • 열거 객체가 가지고 있는 문자열을 리턴한다. 이 때 리턴되는 문자열은 열거 타입을 정의할 때 사용한 상수 이름과 동일하다.
   Week today = Week.SUNDAY;
   String name = today.name();//열거 객체 내부의 문자열인 "SUNDAY"를 리턴하고 name 변수에 저장한다.
  1. ordinal() 메소드

    • 전체 열거 객체 중 몇 번째 열거 객체(순번)인지 알려준다. int 타입으로 반환한다.
   Week today = Week.SUNDAY;
   int ordinal = today.ordinal();
  1. compareTo() 메소드

    • 매개값으로 주어진 열거 객체를 기준으로 전후 몇 번째에 위치하는지를 비교한다. 열거 객체가 매개값의 열거 객체보다 순번이 빠르다면 음수가, 늦다면 양수가 리턴된다.
   Week day1 = Week.MONDAY;
   Week day2 = Week.WEDNESDAY;
   int result1= day1.compareTo(day2); //-2
   int result2= day2.compareTo(day1); //2
  1. valueOf() 메소드

    • 매개값으로 주어지는 문자열과 동일한 문자열을 가지는 열거 객체를 리턴한다. 외부로부터 문자열을 입력 받아 열거 객체로 변환할 때 유용하게 사용할 수 있다.
   Week weekDay = Week.valueOf("SATURDAY");
   // weekday는 Week.SATURDAY 열거객체를 참조하게 된다.
  1. values() 메소드

    • 열거 타입의 모든 열거 객체들을 배열로 만들어 리턴한다. 해당 배열의 각 인덱스 값은 해당 순번의 열거 객체 번지를 참조한다.
   //예시
   Week[] days = Week.values();
   for(Week day : days){
       System.out.println(day);
   }
profile
Done is better than perfect🔥

0개의 댓글