ch05. 참조 타입
05-1. 참조 타입과 참조 변수
[기본 타입과 참조 타입] : ‘저장되는 값’이 다르다.
기본 타입 변수: 변수에 실제 값을 저장
참조 타입 변수: 변수에 객체의 번지를 저장하고, 번지를 통해 객체를 참조
[메모리 사용 영역] : JVM은 운영체제에서 할당받은 메모리 영역을 세부 영역으로 구분
- 메소드 영역 (모든 스레드가 공유)
: JVM 시작할 때 생성
: 코드에서 사용되는 클래스(.class)들을 클래스 로더로 읽어서 클래스 별로 정적 필드, 상수, 메소드 코드, 생성자 코드 분류 저장 - 힙 영역 (객체와 배열 생성)
: 여기에 생성된 객체와 배열은 스택영역 변수나 다른 객체의 필드에서 참조한다.
: 만약 참조하는 변수, 필드 없으면 의미없는 객체가 되어 JVM은 자동 메모리 제거 - JVM 스택 영역 (변수 생성 영역)
: 메소드 호출 시 ‘프레임’ push
: 메소드 종료 시 ‘프레임’ pop 동작 수행
[참조 변수의 ==, != 연산] : 번지 비교 연산
: 참조 타입 변수의 값은 ‘힙 영역의 객체 주소’라서
결국 번지 값을 비교하는 것이다. (즉, 동일한 객체 참조하는지 비교)
[null과 NullPointerException]
참조타입변수가 null값 가지면, 힙 영역의 객체를 참조하지 않는 상태
→ null값 가질 때는 스택 영역에 생성됨
예외 중 하나.
: null값 갖는 참조변수를 통해 (존재하지도 않는 객체)의 데이터나 메소드 코드 사용 시 발생
[String 타입] : 클래스 객체이므로 ‘참조 타입’
- String 객체를 문자열 리터럴로 생성 시.
String name ="신용권";
String hobby = "자바" ;
: 변수는 String 객체 참조하고 있는 상태
: 변수는 스택 영역에 생성, 문자열 리터럴값은 힙 형역의 String객체에 생성
: 변수에는 String객체 번지 값이 저장됨
→ 동일한 문자열 리터럴로 객체 생성 시, 객체 공유함
→ new 객체 생성 연산자로 객체 생성 시,
String name1 = new String("신용권"); //별도로 객체 생성한다.
[참조를 잃은 객체]
String hobby = null; //참조하는 String객체 없다
System.out.println(hobby.length());
//참조변수 hobby가 참조하고 있는 객체의 문자열 길이를 알고 싶음
String name = "홍자바"; //name변수는 String객체 참조하고 있다가
System.out.println(name.length()); //정상 처리
name = null; //참조를 잃은 String 객체 -> JVM은 참조되지 않은 객체를 쓰레기 객체 취급하여 자동 메모리 제거
System.out.println(name.length()); //비정상 처리 (nullPointerException)
: JVM은 참조되지 않은 객체를 쓰레기 객체 취급하여
(쓰레기 수집기) Garbage Collector 로 메모리에서 자동 제거 시킨다.
→ 자바의 메모리 자동 정리 기능
[문자열 비교] | equls() 메소드 사용
- String객체가 달라도, 내부 문자열 값이 동일하면 T 리턴
public class StringEqualsExample {
public static void main(String[] args) {
//객체를 문자열 리터럴로 생성
String strVar1 = "신민철";
String strVar2 = "신민철“ //동일한 문자열 리터럴로 String객체 생성 시, 객체 공유
if(strVar1 == strVar2) { //참조타입 '번지 비교'
System.out.println("참조 객체 동일 ");
}else {
System.out.println("참조 객체 불일치");
}
if(strVar1.equals(strVar2) ) { //내부 문자열 비교
System.out.println("내부 문자열 동일");
}
//객체를 new연산자로 생성
String strVar3 = new String("신민철");
String strVar4 = new String("신민철"); //동일한 문자열 리터럴해도, new객체 별도 생성됨
if(strVar3 == strVar4) { //참조타입 '번지 비교'
System.out.println("참조 객체 동일 ");
}else {
System.out.println("참조 객체 불일치");
}
if(strVar3.equals(strVar4) ) { //내부 문자열 비교
System.out.println("내부 문자열 동일");
}
05-2. 배열
[배열] : 같은 타입의 데이터를 연속된 공간에 나열하여, 각 인덱스 부여한 구조
- 반드시 배열은 동일한 타입의 데이터들만 모아 저장 가능하다.
- 한 번 생성된 배열의 크기 변경 불가능
[배열 변수 선언]
타입[ ] 변수 ;
- 배열은 객체이므로 힙 영역에 생성되고, 배열 변수는 참조변수에 속한다.
- 배열 변수가 선언되면, 배열 변수는 힙 영역의 배열 객체를 참조하는 상태가 된다.
[배열 객체 생성]
**(1)<값 목록으로 배열 객체 생성>**
타입[] 변수 = { 값1, 값2 ...};
- 반드시 처음 변수 선언 시 값 목록 넣어야 한다. (변수 선언 후, 따로 값목록 배열 생성X)
- 중괄호 {}는 배열 객체를 힙에 생성 후, 배열 객체의 번지를 반환한다,
- 배열 변수에는 반환된 번지 저장되어 생성된 객체를 참조하는 상태된다.
✅(특정 인덱스 항목 값 변경) = 대입 연산자 사용
String[] names = {“A”, “B”, “C”};
names[1] = “D”;
✅(변수 선언 후/ 값 목록을 나중) : new연산자 사용 -> 값 목록 지정
타입[] 배열변수 = null;
배열변수 = new 타입[] {값1, 값2, 값3...};
→ 매개값이 배열인 메소드 호출 시,
“값 목록으로 배열 생성 동시에 매개값 사용 원하면”
메소드의 매개값에 ( new 타입[] {값1, 값2, 값3...} ) 넣어 호출한다.
**(2)<new연산자로 배열 객체 생성>**
타입[] 변수 = new 타입[길이];
- 이 경우에는 배열 변수 선언 후에도 new연산자로 배열 생성 가능
- new 연산자로 배열 처음 생성되면, 배열은 각 타입별 기본값으로 자동 초기화된다.
✅(특정 인덱스 항목에 새로운 값 저장) = 대입 연산자 사용
int scores = new int[3];
scores[1] = 83;
[배열 길이] | 배열변수.length
: 배열의 길이는 해당 배열의 length 필드에 저장되어 있기 때문에
배열변수.length; //배열변수가 참조하고 있는 배열 객체의 length필드 읽어온다.
for문 사용해서 배열 전체 루핑 시 유용하게 사용
[main() 메소드 매개값] | String[]args
public static void main (String[] args)
: JVM은 기본적으로 값 목록을 주지 않은 상태인 길이 0의 String배열 생성한 후, main()매개값으로 전달한다.
: main()메소드는 String[] args 매개변수 통해 입력된 배열 길이, 배열 항목값 알 수 있다.
**→ [이클립스에서 main()에 매개값 주는 방법]**
[RUN]-> [Run Configurations] : 실행 구성 -> [Arguments] -> [Program arguments]
- 입력란에 공백으로 구분한 (String) 데이터값 넣으면 된다,
- run -> 실행 구성 -> 인수 -> 프로그램 인수 : 입력란에 데이터값 입력
[다차원 배열]
**(1)<new연산자로 다차원 배열 객체 생성>**
타입[][] = new 타입[길이][길이];
✅(행열 구조 배열 생성)
**int[][] scores = new int[2][3];**
:scores 변수는 scores[2] 배열 객체 참조
:scores[0] 변수는 다시 길이3인 배열 객체 참조
:scores[1] 변수는 다시 길이3인 배열 객체 참조
✅(계단식 구조 배열 생성) : 행 인수만 주고, 열 인수를 나중에 결정
→ 이 형태의 배열 사용시, 배열의 정확한 길이 알고 인덱스 지정해서 사용할 것
int[][] scores = new int[2][];
scores[0] = new int[2];
scores[1] = new int[3];
**(2)<값 목록을 이용한 다차원 배열 객체 생성>**
타입[][] 변수 = { {값1, 값2 }, {값3, 값4, 값5} };
//(1)new연산자로 배열 객체 생성
int[][] mathScores = new int[2][3]; //행열 구조
for(int i = 0; i<mathScores.length; i++) {
for(int j = 0; j<mathScores[i].length; j++ ) {
System.out.println("mathScores["+ i + "]["+j+"] = " + mathScores[i][j]);
}
}
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 j = 0; j<englishScores.length; j++ ) {
System.out.println("englishScores["+i+"]["+j+"]="+englishScores[i][j]);
}
}
System.out.println();
//(2)값목록으로 배열 객체 생성
int[][] javaScores = { {95,80}, {92,96,80}};
for (int i=0; i<javaScores.length; i++) {
for(int j=0; j<javaScores.length; j++) {
System.out.println("javaScores=["+ i +"]["+j+"]"+ javaScores[i][j]);
}
[객체를 참조하는 배열]
기본타입 배열은 배열 항목으로 실제 값을 갖는다.
참조타입 배열은 배열 항목에 참조하는 객체의 번지를 갖는다.
[String[] 배열]
: 배열 변수는 배열 객체 번지 갖고 참조하고 있다.
: 해당 배열 객체 속 내부 배열 항목값은 다시 객체 번지 갖는다.
: 따라서 참조타입의 배열 항목은 다시 참조 변수처럼 취급되어 각 주소값 갖는 객체 참조
따라서 String[] 배열 항목 간에 문자열 비교 == 연산자로 비교시, 객체의 번지가 비교된다.
equals(); 메소드 사용
[배열 복사]
: 배열 한 번 생성하면 크기 변경 불가능
: 더 많은 공간 필요할 경우, 더 큰 새로운 배열 만들어서, 이전 배열 항목값을 복사하여 옮김
**(1)<for 문으로 배열 항목값 복사>**
int[] oldArray = {1,2,3};
int[] newArray = new int[5];
for(int i=0; i<oldArray.length; i++) {
newArray[i] = oldArray[i];
}
(2)< System.arraycopy() 메소드 이용 배열 복사>
System.arraycopy( 원본배열, 복사시작위치, 대상배열, 복사될위치, 복사길이);
:참조타입배열이 복사되면, 복사되는 값은 다시 객체의 번지가 되므로
새 배열의 항목은 이전 배열 항목이 참조하던 객체와 동일하다.
[향상된 for문] : 배열과 컬렉션 쉽게 처리할 목적, 증감식X
for ( 변수 : 배열 ) { // 배열 항목 개수만큼만 반복
//반복할 때마다 배열 각 항목 하나씩 순회하며 변수 저장하여 실행문 감
실행문;
}
05-3. 열거 타입
**열거 타입 : 몇 가지로 제한된 상수 만을 갖는 타입**
열거 타입 변수 : 열거 타입 내부의 열거 상수 1개만 올 수 있다.
[열거 타입 선언]
public enum 열거타입이름 {열거상수1, 열거상수2, ...열거상수5} ;
→ [이클립스에서 열거타입 생성] | [File – New – Enum]
패키지 입력란 : 열거 타입이 속할 패키지 이름
Enum Name 입력란 ; 열거 타입 이름 입력
→ 열거 타입 소스 파일 (.java)가 생성되어 저장되면 (.class) 바이트 코드 파일로 저장
→ 따라서 열거 타입 자체는 메소드 영역에 생성된다. (.class)파일로!
[열거타입 변수 선언] : 변수는 스택 영역에 생성
열거타입 변수 = 열거타입.열거상수 ;
ex) Week today = Week.SUNDAY;
열거타입 Week는 {내부 열거상수} 최초 선언 시 → 메소드 영역에 생성
열거타입 변수 today 선언 시 → 스택 영역에 생성된다.
열거상수 Week.SUNDAY → 힙 영역의 Week 객체로 생성된다.
**(열거상수 = 객체)**
'Java > [문법]_Java(자바)' 카테고리의 다른 글
ch07. 상속 (0) | 2021.08.03 |
---|---|
ch06. 클래스 (0) | 2021.08.02 |
ch04. 흐름 제어문 (조건문과 반복문) (0) | 2021.07.29 |
ch03. 연산자 (0) | 2021.07.29 |
ch02. 변수와 타입 (0) | 2021.07.28 |