[JAVA] 5. 참조 타입

redcarrot01·2021년 5월 3일
0

JAVA

목록 보기
5/9
post-thumbnail

5. 참조 타입

5.1 참조 타입과 참조 변수

참조 타입

메모리의 번지를 통해 객체를 참조

기본타입은 실제 값을 변수에 저장하지만,

참조타입은 번지를 변수에 저장한다.

메모리 타입

메소드 영역

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

정적 필드(static field), 상수(constant), 메소드 코드, 생성자 코드 등을 저장

힙 영역

객체와 배열 생성되는 영역

참조하는 변수나 필드가 없다면, 의미 없는 객체이므로 Garbage Collector으로 자동 제거

JVM 스택 영역

메소드 호출할 때마다 프레임 추가, 메소드 종료되면 프레임 제거

프레임 내부에서는 로컬 변수 스택이 있음, 스택 영역에 변수가 생성되는 시점은 초기화가 될 때, 즉 최초로 변수에 값이 저장될 때임

int [] scores = {10, 20, 30};

배열 변수인 scores는 스택영역에 생성, 하지만 실제 값10,20,30은 힙영역에 생성

자바에서는 배열을 객체로 취급

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

참조 타입에서 이 연산은 동일한 객체를 참조하는지를 볼때 사용

결국 ==,!= 은 번지 값을 비교

동일한 번지 값을 갖고 있다 = 동일한 객체 참조한다

null과 NullPointerException

null = 객체를 참조하지 않는다

null값도 초기값으로 사용 가능, null로 초기화된 참조 변수는 스택 영역에 생성

NullPointerException 이란?

참조 변수가 null값을 가지고 있는 상태에서, 있지도 않은 객체의 필드나 메소드를 사용하면

NullPointerException이 발생한다.

int [] a = null;
a[0] = 10; // 에러 발생

String 타입

String 변수는 스택에 생성,

문자열은 String 객체로 힙에 생성

String name = "aa"; // 방법1
String name1 = "aa"; 

String name2 = new String("aa");  // 방법2

방법1에서 name, name1은 문자열 리터럴이 동일하다면 같은 String 객체를 공유한다.

but,

방법2는 new 연산자를 이용해 힙 영역에 새로운 객체를 만들 때 사용하는 방법이다.

즉, 같은 문자열을 저장했지만 name1, name2은 서로 다른 String 객체를 참조한다.

번지 말고 문자열 비교하는 법
boolean result = str1.equals(str2);

같다면 true, 다르다면 false 반환

String hobby = "dd";
hobby = null

null을 대입함으로써 더이상 String 객체를 참조할 수 없는데,

참조를 잃은 String 객체는 가비지컬렉터가 메모리에서 자동 제거한다.

5.2 배열

배열

무엇 ? 자료구조.

어떤 ? 같은 타입의 데이터를 나열한..

그리고 ? 그 데이터에 인덱스 부여함

배열 선언

두가지 형식 가능

int [] a;
int arr[];

배열도 객체다.

배열 객체는 힙에 생성, 배열 변수는 스택에 생성되고 배열 객체를 참조

배열 생성

객체 생성하려면 값 목록을 이용하거나 new 연산자를 이용하는 방법

값 목록을 배열 생성

타입 [] 변수 = { , , , , ...} //정석


타입 [] 변수;
변수 = { , , , ...}  // 컴파일에러

배열 변수 선언과 배열 객체 생성은 동시에 이루어져야 한다.

배열 변수를 미리 선언한 후, 값 목록들이 나중에 결정되야 한다면 new 연산자 쓰자

String [] n;
n = new String[] {"dd", "ss"}; 

// 메소드의 매개값이 배열일 경우도 마찬가지
int result = add({90, 85, 90}); // 컴파일 에러
int result = add( new int[] {90, 85, 90});

new 연산자로 배열 생성

new 연산자로 배열을 처음 생성할 경우 배열은 자동으로 기본값으로 초기화

타입 [] 변수 = new 타입[길이];

타입[] 변수 = null;
변수 = new 타입[길이];

타입[] 변수 = new 타입[길이];

타입별 배열의 초기값

배열 길이

배열변수.length

명령 라인 입력

main() 메소드는 String [] args 매개 변수를 통해서 명령 라인에서 입력된 데이터의 수(배열의 길이)와 입력된 데이터(배열의 항목 값)를 알 수 있게 한다.

public static void main(String[] args)

// 메인문의 의미는 아래와 같다
// args는 메인 메소드 호출시 전달
String[] args = { };

public static void main(String[] args){
}

다차원배열

//1.  2행 3열 배열 생성
int [][] scores = new int[2][3];  
scores.length // 2
scores[0].length // 3
scores[1].length // 3

//2. 특이한 계단식 구조 
int [][] scores = new int[2][];
scores[0] = new int[2]; 
scotes[1] = new int[3]; 
scores.length // 2
scores[0].length // 2
scores[1].length // 3
    
//3. 그룹화된 값 중괄호 이용
int [][] scores = {{11, 22}, {33,44}}

2번에서 행렬 구조가 아닌 계단식 구조를 가질 수 있다.

scores[0] = new int[2]; -> |0|1|

scotes[1] = new int[3]; -> |0|1|2|

객체를 참조하는 배열

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]); //1
		System.out.println( strArray[0] == strArray[2] );  //2
		System.out.println( strArray[0].equals(strArray[2]) ); //3
	} 
}
// true
// false
// true

1번 : 두 배열 객체가 동일한 String 객체 참조

2번 : 서로 다른 객체 참조

배열 복사

두가지 방법이 있다.

  1. for 문
public class ArrayCopyByForExample {
	public static void main(String[] args) {
		int[] oldIntArray = { 1, 2, 3 };
		int[] newIntArray = new int[5]; // 0으로 초기화된 배열 (길이 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 0 0
  1. System.arraycopy() 메소드
System.arraycopy( Object src, int srcPos, Object dest, int destPos, int length);

src : 원본 배열

srcPos : 복사할 항목의 시작 인덱스

dest : 새배열

destPos : 새배열에 붙일 시작 인덱스

length : 복사 개수

public class ArrayCopyExample {
	public static void main(String[] args) {
		String[] oldStrArray = { "java", "array", "copy" };
		String[] newStrArray = new String[5]; // null로 초기화된 배열 (길이 5)
		
		System.arraycopy( oldStrArray, 0, newStrArray, 0, oldStrArray.length);
		
		for(int i=0; i<newStrArray.length; i++) {
			System.out.print(newStrArray[i] + ", ");
		}
	}
}

// java, array, copy, null, null

자바의 향상된 for문

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);

	} 
}

5.3 열거 타입

열거 타입은 한정된 값인 열거 상수 중에서 하나의 상수를 저장하는 타입

Week today; // Week가 열거 타입, today 변수
today = Week.FRIDAY; // FRIDAY가 열거 상수

열거 타입 선언

열거 타입의 이름을 정하고, 해당 이름으로 소스파일(.java)을 생성

public enum Week { // Week가 열거 타입, public enum 열거타입선언 위한 키워드
	  MONDAY,
	  TUESDAY,
	  WEDNESDAY,
	  THURSDAY,
	  FRIDAY,
	  SATURDAY,
	  SUNDAY
} // 괄호 안 열거 상수 선언

열거 타입 변수

// 열거타입 변수;
Week today;

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

열거타입은 참조타입

열거상수는 객체

Week week1 = Week.SATURDAY;
Week week2 = Week.SATURDAY;
System.out.prinln(week1 == week2); // true

week1과 week2는 동일한 Week객체를 참조하므로

  • 자바의 날짜 요일 시간 클래스
Calender now = Calender.getInstance();

int year = now.get(Calender.YEAR); //연
int month = now.get(Calender.MONTH)+1; //월 .. 이런식

관심 있을 만한 포스트

0개의 댓글