[혼공자바] Ch05 정리
1. 참조 타입과 참조 변수
1-1. 기본 타입과 참조 타입
-
기본 타입 변수 : 실제 값을 변수 안에 저장
-
byte, char, short, int, long, float, double, boolean
ex) int age = 25;
-
-
참조 타입 변수 : 메모리의 번지를 변수 안에 저장
-
배열, 열거 클래스, 인터 페이스 변수
ex) String name = “혼공컴운”;
-
1-2. 메모리 사용 영역
- JVM은 운영체제에서 할당 받은 메모리 영역(Runtime Data Area)을 다음과 같이 세부 영역으로 구분해서 사용한다
출처 : 혼자 공부하는 컴퓨터 구조 + 운영체제 p.166
- 메소드 영역
- JVM이 시작할 때 생성되고 모든 스레드가 공유하는 영역
- 코드에서 사용되는 클래스들을 클래스 로더로 읽어 클래스 별로 정적 필드와 상수, 메소드 코드, 생성자 코드 등을 분류해서 저장한다.
- 힙 영역
- 객채와 배열이 생성되는 영역
- 여기에 생성된 객체와 배열은 JVM 스택 영역의 변수나 다른 객체의 필드에서 참조
- 만일 참조하는 변수나 필드가 없다면 의미 없는 객체자 되기 때문에 JVM이 이것을 쓰레기로 수집하고 쓰레기 수집기를 실행시켜 자동으로 제거한다.
-
쓰레기 수집기(garbage collector)
➡ 메모리 관리 기법 중 하나.
➡ 자바에선 JVM의 쓰레기 수집기를 이용해 자동적으로 사용하지 않는 객체를 메모리에서 제거한다.
✔️ 객체를 제거하기 전 수행하고 싶은 일이 있을 때
➡ 쓰레기 수집기가 객체를 제거하기 전 중요한 데이터를 저장하고 싶을 때, 클래스 내에 객체 소멸자(finalize())를 재정의하여 객체가 소멸될 때 실행할 코드를 입력할 수 있다.
- 객채와 배열이 생성되는 영역
-
JVM 스택 영역
- 메소드를 호출할 때마다 프레임을 추가하고 메소드가 종료되면 해당 프레임을 제거하는 동작을 수행한다.
- 프레임 내부에는 로컬변수 스택이 있는데, 기본 타입 변수와 참조 타입 변수가 추가되거나 제거된다.
- 스택 영역
- 변수가 생성되는 시점은 초기화(최초로 변수에 값이 저장)될 때이다.
- 변수는 선언된 블록 안에서만 스택에 존재하고 블록을 벗어나면 제거된다.
char v1 = 'A';
if (v1 == 'A'){
int V2 = 100; // v2, v3은 if 블록 내부가 실행되고 있을 때만 스택 영역에 존재하고 블록을 빠져나가면 소멸됨.
double v3 = 3.14;
}
boolean v4 = true;
1-3. 참조 변수의 ==, != 연산
- 참조 타입 변수들 간의 ==, != 연산은 동일한 객체를 참조하는지, 다른 객체를 참조하는 지 알아볼 때 사용
- 동일한 번지 값을 갖고 있다면, 동일한 객체를 참조하는 것.
1-4. null과 NullPointerException
-
null
- 참조 타입 변수가 객체(힙 영역)를 참조하지 않는다는 의미의 값
- null값도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 저장된다.
- 참조 변수가 null을 가지고 있을 경우
- 참조 객체가 없으므로 변수를 통해 객체 사용 불가
-
예외 : 프로그램 실행 도중에 발생하는 오류
-
NullPointerException
-
참조 변수를 사용하면서 가장 많이 발생하는 예외
-
참조 타입 변수를 잘못 사용하면 발생
- null 상태에서 있지도 않은 객체의 데이터(필드)나 메소드를 사용하는 코드를 실행하면 발생
int[] intArray = null; // 참조 변수(배열) intArray[0] = 10; //NullPointerException 발생 -> intArray 변수가 참조하는 배열 객체가 없기 때문 String str = null; // 참조 타입(클래스) System.out.println(str.length()); //NullPointerException 발생 -> str 변수가 참조하는 String 객체가 없기 때문
-
NullPointerException 해결법 : 참조 변수를 추적해서 객체를 참조하도록 수정
-
1-5. String 타입
String name; // String 변수 우선 선언
name = "신용권"; // 큰따옴표로 감싼 문자열 리터럴을 대입해 String 변수에 문자열 저장
String hobby = "자바"; // 변수 선언과 동시에 문자열 저장
-
문자열을 String 변수에 저장한다는 말은 엄밀히 말해 틀린 표현이다.
- 문자열이 직접 변수에 저장되는 것이 아닌 String 객체로 생성되고 변수는 String 객체를 참조하기 때문
- 하지만 일반적으로 String 변수에 저장한다고 표현한다.
-
자바는 문자열 리터럴이 동일하다면 String 객체를 공유하도록 되어 있다.
-
new 연산자(객체 생성 연산자)
- 힙 영역에 새로운 객체를 만들 때 사용하는 연산자
- 변수에 문자열을 저장할 경우에 문자열 리터럴을 사용하지만 new 연산자를 사용해 직접 String 객체 생성 가능
String name1 = new String("신용권"); String name2 = new String("신용권"); //name1 과 name2는 서로 다른 String 객체를 참조한다.
- 동일한 문자열 리터럴로 String 객체를 생성했을 경우 ‘==’ 연산 결과 ➡ true
- new 연산자로 String 객체를 생성했을 경우 ‘==’ 연산 결과 ➡ false
-
내부 문자열을 비교하고 싶을 때
- String 객체의 equals() 메소드 사용
boolean result = str1.equals(str2)
-
더 이상 String 객체를 참조하고 싶지 않을 때
String hongong = "혼공컴운"; // String 객체 참조 hongong = null; // String 객체 참조 X
- 참조를 잃은 String 객체는 쓰레기 취급하고 쓰레기 수집기를 구동시켜 메모리에서 자동 제거한다.
2. 배열
2-1. 배열(참조 변수)
- 데이터를 연속된 공간에 나열하고, 각 데이터에 인덱스를 부여해 놓은 자료구조
- 이러한 성질 때문에 중간 인덱스의 값을 삽입하거나 삭제하기 어렵고, 선언 후 배열의 인덱스 수를 늘릴 수 없다.
- 같은 타입의 데이터만 저장할 수 있다.
- 만약 다른 타입의 값을 저장하려고 하면 타입 불일지(Type mismatch) 컴파일 에러 발생
- 인덱스
- 0에서부터 “문자열(혹은 배열) 길이 -1”까지의 번호를 매긴 것.
- 배열과 같은 선형 자료구조는 인덱스로 원소에 접근할 수 있다.
-
열거 타입(enumeration type)
-
한정된 값만을 갖는 자료형
enum Week{ SUNDAY, MUNDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY //열거 상수 }
-
2-2. 배열 선언
- 배열을 사용하기 위해 배열 변수를 선언해야한다.
-
배열도 객체이므로 힙 영역에 생성되고 배열 변수는 힙 영역의 배열 객체 참조
- 만일 참조할 배열 객체가 없다면 배열 변수는 null 값으로 초기화될 수 있다.
- 배열 변수가 null값을 가진 상태에서 변수[인덱스]로 값을 읽거나 저장하게 되면 NullPointerException 발생
//배열 선언
int[] intArray; //형식1
int intArray[]; //형식2
int[] intArray = null; //NullPointerException
2-3 배열 생성
- 배열 객채 생성 ➡ 값 목록 이용 or new 연산자를 이용
- {}는 주어진 값들을 항목으로 가지는 배열 객체를 힙에 생성하고, 배열 객체의 번지를 리턴한다.
- 배열 변수는 리턴된 번지를 저장함으로써 참조가 이루어진다.
// 배열 생성
타입[] 변수 = {v1, v2 ,v3, ...}; // 값 목록으로 배열 생성
//오류
타입[] 변수;
변수 = {v1, v2, v3, ...}// 배열 변수 선언 후 다른 실행문에서 중괄호 사용한 배열 생성 허용X
------------------------
// 배열 변수를 미리 선언한 후 값 목록들이 나중에 결정되는 상황일 때
변수 = new 타입[] = {v1, v2, v3,...}; // new 연산자를 이용한 배열 생성
// 배열 변수를 미리 선언한 후 new 연산자로 배열 생성
타입[] 변수 = null;
변수 = new 타입[길이]
// 배열 길이
int[] intArray = {10, 20, 30};
int num = intArray.length;]
//배열 복사
System.arraycopy(arr1, 0, arr2, 0, arr1.length)
// 향상된 for문
for (타입 변수 : 배열){
실행문
}
// 다차원 배열(2x3 행렬)
int[][] scores = new int[2][3];
2-4 확인 문제
-
배열을 생성하는 방법으로 틀린 것
-
int[] array; array ={1, 2, 3};
배열 변수 선언 후 다른 행문에서 중괄호 사용한 배열 생성 허용X
-
-
배열의 기본 초기값에 대한 설명으로 틀린 것
-
boolean 타입 배열 항목의 기본 초기값은 true이다.
➡ true가 아닌 false이다.
-
-
배열 길이
➡ array.length = 3
➡ array[2].length = 5
-
for문을 이용해서 배열의 항목에서 최대값 구해보기
**<코드>**코드>
public class Main { public static void main(String[] args) { int max = 0; int[] array = {1, 5, 3, 8, 2}; // 코드 작성 구간 for (int i = 0; i < array.length; i++){ if (array[i] > max){ max = array[i]; } } // System.out.println("max: " + max); } }
**<결과>**결과>
-
중첩 for문을 이용해서 주어진 배열의 전체 항목의 합과 평균값 구해보기
**<코드>**코드>
public class Main { public static void main(String[] args) { int[][] array = { {95, 86}, {83, 92, 96}, {78, 83, 93, 87, 88} }; int sum = 0; double avg = 0.0; //코드 작성 구간 int cnt = 0; for(int i = 0; i < array.length; i++){ for(int j = 0; j < array[i].length; j++){ sum += array[i][j]; cnt++; } } avg = (double)sum / (double)cnt; // System.out.println("sum: " + sum); System.out.println("avg: " + avg); } }
**<결과>**결과>
-
실행결과를 보고 코드 작성해보기
**<코드>**코드>
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
boolean run = true;
int studentNum = 0;
int[] scores = null;
Scanner scanner = new Scanner(System.in);
while(run){
System.out.println("----------------------------------------------");
System.out.println("1.학생수 | 2.점수입력 | 3.점수리스트 | 4.분석 | 5.종료");
System.out.println("----------------------------------------------");
System.out.print("선택> ");
int selecNo = Integer.parseInt(scanner.nextLine());
if (selecNo == 1){
// 코드 작성
System.out.print("학생수> " );
studentNum = Integer.parseInt(scanner.nextLine());
}
else if(selecNo == 2){
// 코드 작성
scores = new int[studentNum];
for(int i = 0; i < scores.length; i++){
System.out.print("scores["+ i + "]> ");
scores[i] = Integer.parseInt(scanner.nextLine());
}
}
else if(selecNo == 3) {
// 코드 작성
for (int i = 0; i < scores.length; i++) {
System.out.println("scores[" + i + "]> " + scores[i]);
}
}
else if(selecNo == 4){
// 코드 작성
int max = -1000000;
int sum = 0;
double avg = 0.0;
for(int i =0; i < scores.length; i++){
if (scores[i] > max){
max = scores[i];
}
sum += scores[i];
}
avg = (double)sum / (double)scores.length;
System.out.println("최고 점수: " + max);
System.out.println("평균 점수: " + avg);
}
else if(selecNo == 5){
run = false;
}
}
System.out.print("프로그램 종료" );
}
}
**<결과>**결과>
댓글남기기