Java/이것이자바다_개념정리

Java 기초 정리 2차_5)참조 타입_이것이 자바다

김쟈워니 2024. 6. 5. 11:29
데이터 타입 분류
  • 자바의 데이터 타입
    • 기본타입(primitive type)
    • 참조타입(reference type)
      • 객체(object)의 번지를 참조하는 타입
      • 배열, 열거, 클래스, 인터페이스 타입

  • 기본 타입으로 선언된 변수와 참조 타입으로 선언된 변수
    • 변수들은 모두 스택(stack)이라는 메모리 영역에 생성 
    • 차이점
      • 기본 타입으로 선언된 변수는 값 자체를 저장
      • 참조 타입으로 선언된 변수는 객체가 생성된 메모리 번지를 저장

메모리 사용 영역

  • 메소드 영역
    • 바이트 코드 파일을 읽은 내용이 저장되는 영역
      • 클래스별로 상수, 정적 필드, 메소드 콛, 생성자 코드 등이 저장
  • 힙 영역
    • 객체가 생성되는 영역
      • 객체의 번지는 메서드 영역과 스택 영역의 상수와 변수에서 참조할 수 있음
  • 스택 영역
    • 메서드를 호출할 때마다 생성되는 프레임(Frame)이 저장되는 영역
      • 프레임 내부에는 로컬 변수 스택이 잇음
        • 기본 타입 변수와 참조 타입 변수가 생성되고 제거
    • 메서드 호출이 끝나면 프레임은 자동으로 제거

참조 타입 변수의 ==,!= 연산
  • ==,!= 연산자는 변수의 값이 같은지, 아닌지를 조사
    • 참조 타입 변수에서의 ==, != 연산자는 번지를 비교하는 것
      • 번지가 같다면 동일한 객체를 참조, 다르다면 다른 객체를 참조
package ch05.sec03;

public class ReferenceVariableCompareExample {

	public static void main(String[] args) {
		int [] arr1;
		int [] arr2;
		int [] arr3;
		
		arr1=new int[] {1,2,3};
		arr2=new int[] {1,2,3};
		arr3=arr2;
		
		System.out.println(arr1==arr2);
		System.out.println(arr2==arr3);
	
	}

}
=====================================================
콘솔출력문
=====================================================
false
true

null 과 NullPointerException
  • 참조 타입 변수는 아직 변수를 저장하고 있지 않다는 뜻으로 null(널) 값을 가질 수 있음
    • null도 초기값으로 사용할 수 있기 때문에 null로 초기화된 참조 변수는 스택 영역에 생성됨
    • 참조 타입 변수가 null 값을 가지는지 확인하려면 ==,!= 연산을 수행할 수 있음
  • NullPointerException
    • 자바는 프로그램 실행 도중 발생하는 오류를 예외(Exception)이라고 부름
    • 참조 변수를 사용하면서 가장 많이 발생하는 예외
    • 변수가 null 인 상태에서 객체의 데이터나 메서드를 사용하려 할 때 이 예외 발생
  • 예외 발생 예시
package ch05.sec04;

public class NullPointerExceptionExample {
	public static void main(String[] args) {
		int[] int array = null;
		intArray[0] = 10;
		
		String str = null;
		System.out.println("총 문자 수: "+ str.length());
	}
}
============================================================
콘솔 출력문
============================================================
Exception in thread "main" java.lang.Error: Unresolved compilation problems: 
	Syntax error, insert "VariableDeclarators" to complete LocalVariableDeclaration
	Syntax error, insert ";" to complete BlockStatements
	Type mismatch: cannot convert from null to int
	intArray cannot be resolved to a variable

	at ch05.sec04.NullPointerExceptionExample.main(NullPointerExceptionExample.java:5)
  • NullPointerException이 발생하면 예외가 발생된 곳에서 null 인 상태의 참조변수가 사용되고 있음을 의미
    • 해결을 위해선 참조 변수가 객체를 정확히 참조하도록 번지를 대입
    • 일부러 참조 타입 변수에 null 을 대입하기도 함
      • 어떤 변수에서도 객체를 참조하지 않으면 해당 객체는 프로그램에서 사용할 수 없는 객체가 됨
      • 힙 메모리에는 있지만, 위치 정보를 몰라 사용할 수 없게 됨
      • 가비지컬렉터를 실행시켜 자동으로 제거
package ch05.sec04;

public class GarbageObjectExample {

	public static void main(String[] args) {
		String hobby="여행";
		hobby = null;
		
		String kind1="자동차";
		String kind2=kind1;
		kind1=null;
		System.out.println("kind2: "+ kind2);
	}

}

문자열(String) 타입
  • 자바의 문자열은 String 객체로 생성
  • 문자열 리터럴이 동일하다면 String 객체를 공유
  • new 연산자로 직접 String 객체를 대입할 수 있음
  • 내부 문자열 값을 비교할때는 equals() 메소드, 번지수를 비교할 때는 ==,!= 연산을 사용
  • 문자열에서 특정 위치의 문자를 얻고 싶다면 charAt() 메소드 이용
    • charAt()메서드는 매개값으로 주어진 인덱스의 문자를 리턴
      • 인덱스란 0에서부터 '문자열의 길이 -1'까지의 번호
  • 문자열에서 문자의 개수를 얻고 싶다면 legnth()메서드를 사용
  • 문자열에서 특정 문자열을 다른 문자열로 대체해고 싶다면 replace() 메서드를 사용
    • replace메서드는 기존 문자열은 그대로 두고, 대체한 새로운 문자열을 리턴
  • 문자열에서 특정 위치의 문자열을 잘라내어 가져오고 싶다면 substring() 메서드를 사용
    • substring(int beginIndex), beginIndex에서 끝까지 잘라내기
    • substring(int beginIndex, int endIndex), beginIndex에서 endIndex 앞까지 잘라내기
  • 문자열에서 특정 문자열의 위치를 찾고자 할 때에는 indexOf() 메서드를 사용
    • indexOf()메서드는 주어진 문자열이 시작되는 인덱스를 리턴
    • 만약 주어진 문자열이 포함되어있지 않으면 indexOf()메서드는 -1을 리턴
  • 특정 문자열이 단순히 포함되어 있는지만 조사하고 싶으면 contains()메서드를 사용
    • 원하는 문자열이 포함되어 있으면 contains() 메서드는 true리턴, 그렇지 않으면 false 리턴
  • 문자열이 구분자를 사용하여 여러 개의 문자여로 구성되어 있을 경우, 이를 따로 분리해서 얻고 싶으면 split()메서드를 사용 
package ch05.sec05;

public class EqualsExample {

	public static void main(String[] args) {
		String strVar1="홍길동";
		String strVar2="홍길동";
		
		if(strVar1== strVar2) {
			System.out.println("strVar1과 strVar2는 참조가 같음");
		}else {
			System.out.println("strVar1과 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는 문자열이 같음");
		}
		
	}

}
==========================================================================
콘솔 출력문
==========================================================================
strVar1과 strVar2는 참조가 같음
strVar1과 strVar2는 문자열이 같음
strVar3과 strVar4는 참조가 다름
strVar3과 strVar4는 문자열이 같음​
  • strVar1과 strVar2 는 변수에 문자열 리터럴을 대입하는 방식으로 객체 생성
    • 문자열 리터럴이 동일하여 String 객체를 공유
      • 참조 타입에서 ==,!= 연산을 시행하면 번지를 비교, strVar1 ,strVar2는 번지수 동일
  • strVar3와 strVar4는 객체를 생성하는 방식으로 값을 대입
    • 각각 다른 객체를 생성하기 떄문에 == ,!= 연산을 시행 했을 때 strVar3,strVar4가 문자열은 동일하지만 번지수는 다른 것을 확인 할 수 있음
package ch05.sec05;

public class EmptyStringExample {

	public static void main(String[] args) {
		String hobby="";
	if(hobby.equals("")) {
		System.out.println("hobby 변수가 참조하는 String 객체는 빈 문자열");
	}
	}

}
===========================================================================
콘솔 출력문
===========================================================================
hobby 변수가 참조하는 String 객체는 빈 문자열
  • String 변수에 빈 문자열(" ")을 대입할 수도 있음
package ch05.sec05;

public class CharAtExample {
	public static void main(String[] args) {
		String ssn="9506241230123";
		char sex = ssn.charAt(6);
		switch(sex) {
		case '1':
		case '3':
			System.out.println("남자입니다.");
			break;
		case '2':
		case '4':
			System.out.println("여자입니다.");
			break;
			
		}
	}

}
===================================================
코드 출력문
===================================================
남자입니다.
  • charAt([인덱스 번호]) 메서드를 이용하여 주민번호의 7번째자리 (인덱스 6) 의 값을 구분하여 성별을 판단하는 프로그램을 생성
package ch05.sec05;

public class LengthExample {

	public static void main(String[] args) {
		String ssn ="9506241230123";
		int length =ssn.length();
		if(length ==13) {
			System.out.println("주민등록 번호 자릿수가 맞습니다.");
		} else {
			System.out.println("주민등록 번호 자릿수가 틀립니다.");
		}
	}

}
=====================================================================
콘솔 출력문
=====================================================================
주민등록 번호 자릿수가 맞습니다.
  • length() 메서드를 통해서 입력받은 문자열의 길이가 주민등록 번호의 자릿수와 동일한지 판단하는 프로그램 생성
package ch05.sec05;

public class ReplaceExample {

	public static void main(String[] args) {
		String oldStr = "자바 문자열은 불변입니다. 자바 문자열은 String 입니다.";
		String newStr = oldStr.replace("자바","JAVA");
		
		System.out.println(oldStr);
		System.out.println(newStr);
	}

}
=======================================================================================
콘솔 출력문
=======================================================================================
자바 문자열은 불변입니다. 자바 문자열은 String 입니다.
JAVA 문자열은 불변입니다. JAVA 문자열은 String 입니다.
  • String 객체의 문자열은 변경이 불가한 특성을 갖기 때문에 replace()메소드가 리턴하는 문자열은 원래 문자열의 수정본이 아니라 완전히 새로운 문자열
  • 즉, oldStr에서 newStr을 생성하는 과정은 동일한 번지수의 값이 바뀌는 것이 아닌, 새로운 번짓수에 대입되는 것 
package ch05.sec05;

public class SubStringExample {

	public static void main(String[] args) {
		String ssn="880815-1234567";
		
		String firstNum=ssn.substring(0,6);
		System.out.println(firstNum);
		
		String secondNum=ssn.substring(7);
		System.out.println(secondNum);
	}

}
==============================================
콘솔출력문
==============================================
880815
1234567
  • firstNum 은 ssn이라는 문자열을 substring(0,6)으로 0부터 6번째 앞까지,즉 0부터 5번째 자리까지 담음
  • secondNum 은 ssn이라는 문자열을 substring(7)로 7번째부터 끝까지 자리를 담음
package ch05.sec05;

public class IndexOfContainsExample {

	public static void main(String[] args) {
		String subject ="자바 프로그래밍";
		
		int location = subject.indexOf("프로그래밍");
		System.out.println(location);
		String subString=subject.substring(location);
		System.out.println(subString);
		
		location = subject.indexOf("자바");
		if(location!=-1) {
			System.out.println("자바와 관련된 책이군요");
		} else {
			System.out.println("자바와 관련 없는 책이군요");
		}
		boolean result =subject.contains("자바");
		if(result) {
			System.out.println("자바와 관련된 책이군요.");
		} else {
			System.out.println("자바와 관련 없는 책이군요.");
		}
	}

}
===============================================================
콘솔 출력문
===============================================================
3
프로그래밍
자바와 관련된 책이군요
자바와 관련된 책이군요.
  • indexOf() 메서드를 사용하여 문자열에 프로그래밍이 시작하는 인덱스를 찾아냄
  • idexOf()메서드, contains()메서드를 통하여 해당 교과목이 자바와 관련있는 교과인지 확인하는 프로그램 
package ch05.sec05;

public class SplitExample {

	public static void main(String[] args) {
		String board="1,자바 학습, 참조 타입 String을 학습합니다., 홍길동";
		//문자열 분리
		String[] tokens=board.split(",");
		
		//인덱스 별로 읽기
		System.out.println("번호: " + tokens[0]);
		System.out.println("제목: " + tokens[1]);
		System.out.println("내용: " + tokens[2]);
		System.out.println("성명: " + tokens[3]);
		System.out.println();
		
		//for문을 이용한 읽기
	for(int i=0; i<tokens.length; i++) {
		System.out.println(tokens[i]);
	}
	}

}
===================================================================================
콘솔 출력문
===================================================================================
번호: 1
제목: 자바 학습
내용:  참조 타입 String을 학습합니다.
성명:  홍길동

1
자바 학습
 참조 타입 String을 학습합니다.
 홍길동

배열(Array) 타입
변수는 하나의 값만 저장
저장해야 할 값의 수가 많아지면 그만큼 많은 변수가 필요

배열(Array)

  • 많은 양의 값을 다루는 효율적인 방법
  • 연속된 공간에 값을 나열시키고, 각 값에 인덱스(index)를 부여해놓은 자료구조
    • 인덱스는 대괄호[] 와 함께 사용하여 각 항목의 값을 읽거나 저장하는데 사용
  • 배열은 같은 타입의 값만 관리
  • 배열의 길이는 선언 이후 늘리거나 줄일 수 없음
  • 배열변수는 참조 변수
  • 배열도 객체이므로 힙 영역에 생성되고, 배열 변수는 힙 영역의 배열 주소를 저장

배열 변수 선언 두 가지 방법

1) 타입[] 변수;
2) 타입 변수[];
  • 관례적으로는 첫 번째 방법을 주로 사용
  • 참조할 배열이 없다면 배열 변수도 null로 초기화 할 수 있음
    • 단, 만일 배열 변수가 null 값을 가진 상태에서 변수[인덱스]로 값을 읽거나 저장하게 되면 NullPointerException 이 발생

값 목록으로 배열 생성

package ch05.sec06;

public class ArrayCreateByValueListExample1 {

	public static void main(String[] args) {
		//배열 변수 선언과 생성
		String[] season = {"Spring","Summer","Fall","Winter"};
		
		//배열의 항목값 읽기
		System.out.println("season[0] : " + season[0]);
		System.out.println("season[1] : " + season[1]);
		System.out.println("season[2] : " + season[2]);
		System.out.println("season[3] : " + season[3]);
	
		//인덱스 1번 항목의 값 변경
		season[1]="여름";
		
		System.out.println("season[1] : " + season[1]);
		System.out.println();
		
		//배열 변수 선언과 배열 생성
		int[] scores= {83,90,87};
		
		//총합과 평균 구하기
		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);
	}
	

}
=========================================================================
콘솔 출력문
=========================================================================
season[0] : Spring
season[1] : Summer
season[2] : Fall
season[3] : Winter
season[1] : 여름

총합: 260
평균 : 86.66666666666667
  • 배열에 저장될 값의 목록이 있다면 타입[] 변수 = {값0,값1,값2,값3,...}; 과 같이 배열을 생성할 수 있음
package ch05.sec06;

public class ArrayCreatByValueListExample2 {

	public static void main(String[] args) {
		//배열 변수 선언
		int[] scores;
		
		//배열 변수에 배열을 대입
		scores= new int[] {83,90,97};
		
		// 배열 항목의 총합을 구하고 출력
		int sum1 = 0;
		for(int i=0; i<3; i++) {
			sum1 += scores[i];
		}
		System.out.println("총합: "+ sum1);
		
		//배열을 매개값으로 주고, printItem() 메서드 호출
		printItem(new int[] {83,90,87});
	}
	//printItem() 메서드 선언
	public static void printItem(int[] scores) {
		//매개 변수가 참조하는 배열의 항목을 출력
		for(int i=0; i<3;i++) {
			System.out.println("scroe[" + i + "]: " + scores[i]);
		}
	}

}
=================================================================
콘솔 출력문
=================================================================
총합: 270
scroe[0]: 83
scroe[1]: 90
scroe[2]: 87
  • 중괄호{} 로 감싼 값의 목록을 배열 변수에 대입할 때 주의할 점이 있음
    • 배열 변수를 미리 선언한 후에는 값 목록을 변수에 대입할 수 없음
    • 배열 변수를 선언한 시점과 값 목록이 대입된느 시점이 다르다면 new 타입[] 을 중괄호 앞에 붙여주어야 함
    • 타입은 배열 변수를 선언할 때 사용한 타입과 동일하게 함.
    • 메소드의 매개변수가 배열 타입일 경우에도 매개값으로 중괄호 감싼 값 목록을 주는 게 아니라 new 타입[] 을 중괄호 앞에 붙여주어야 함

new 연산자로 배열 생성

  • 값의 목록은 없지만 향후 값들을 저장할 목적으로 배열을 미리 생성할 경우, new 연산자를 통해 배열 객체를 생성시킴
타입[] 변수 = new 타입[길이];
  • 길이는 배열이 저장할 수 있는 항목의 수 
  • new 연산자는 해당 길이의 배열을 생성하고 배열의 번지를 리턴하기 때문에 배열 변수에 대입할 수 있음
  • 이미 배열 변수가 선언된 후에도 아래와 같이 대입 가능
타입[] 변수 = null;
변수 = new 타입 [길이];
  • new 연산자로 배열을 처음생성하면 배열 항목은 기본값으로 초기화됨
  • 정수 배열은 0(문자는 '\u0000'), 실수 배열은 0.0, 논리 배열은 fasle, 참조 배열은 null 로 초기화 됨
  • String 타입 배열도 참조배열이기 때문에 null 로 초기화 
package ch05.sec06;

public class ArrayCreateByNewExample {

	public static void main(String[] args) {
		// 정수형 배열 변수 선언과 배열 생성
		int[] arr1 = new int[3];
		// 배열 항목의 초기값 출력
		for (int i = 0; i < 3; i++) {
			System.out.print("arr1[" + i + "] :" + arr1[i] + ",");

		}
		System.out.println();
		// 배열 항목의 값 변경
		arr1[0] = 10;
		arr1[1] = 20;
		arr1[2] = 30;

		// 배열 항목의 변경 값 출력
		for (int i = 0; i < 3; i++) {
			System.out.print("arr1[" + i + "]: " + arr1[i] + ",");
		}
		System.out.println("\n");

		// 실수형 배열 변수 선언과 배열 생성
		double[] arr2 = new double[3];

		// 배열 항목의 초기값 출력
		for (int i = 0; i < 3; i++) {
			System.out.print("arr2[" + i + "]:" + arr2[i] + ",");
		}

		System.out.println();
		arr2[0] = 0.1;
		arr2[1] = 0.2;
		arr2[2] = 0.3;

		for (int i = 0; i < 3; i++) {
			System.out.print("arr2[" + i + "]:" + arr2[i] + ",");
		}
		System.out.println("\n");

		// 배열 변수 선언과 배열 생성
		String[] arr3 = new String[3];
		for (int i = 0; i < 3; i++) {
			System.out.print("arr3[" + i + "]:" + arr3[i] + ",");
		}
		System.out.println();
		arr3[0] = "1월";
		arr3[1] = "2월";
		arr3[2] = "3월";

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

}
====================================================================
콘솔 출력문
====================================================================
arr1[0] :0,arr1[1] :0,arr1[2] :0,
arr1[0]: 10,arr1[1]: 20,arr1[2]: 30,

arr2[0]:0.0,arr2[1]:0.0,arr2[2]:0.0,
arr2[0]:0.1,arr2[1]:0.2,arr2[2]:0.3,

arr3[0]:null,arr3[1]:null,arr3[2]:null,
arr3[0]:1월,arr3[1]:2월,arr3[2]:3월,
  • 정수배열의 초기화 값, 실수배열의 초기화 값,  참조배열의 초기화 값 을 보여주는 예제

배열 길이

  • 배열의 길이
    • 배열에 저장할 수 있는 항목 수
배열변수.length;
  •  배열의 길이를 얻는 방법
  •  배열의 길이는 읽기만 가능하므로 값을 변경할 수 없음
package ch05.sec06;

public class ArrayLengthExample {

	public static void main(String[] args) {
		// 배열 변수 선언과 배열 변수 대입
		int[] scores = { 84, 90, 96 };

		// 배열 항목의 총합 구하기
		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);
	}

}
==================================================
콘솔 출력문
==================================================
총합: 270
평균: 90.0
  • for 문의 조건식에서 < 연산자를 사용한 이유는 배열의 마지막 인덱스는 배열 길이보다 1이 적기 때문
    • 인덱스를 초과해서 사용하면 ArrayIndexOutOfBoundsException이 발생

다차원 배열

배열 항목에는 또 다른 배열이 대입될 수 있는데, 이러한 배열을 다 차원 배열이라고 함

다차원 배열의 메모리구조

  • 스택 영역에는 arr 변수만 존재, 이 변수는 2차원 배열의 시작주소를 저장하여 힙 영역의 배열을 가리킴
  • 힙 영역에 실제 배열데이터가 저장
    • 처음으로 arr 이 가리키는 것은 각 배열의 길이, arr[0] 과 arr[1] 을 가르킴
    • arr[0]과 arr[1] 은 각각 그 안에 배열들을 참조함. 

값 목록으로 다차원 배열 생성

 값 목록으로 다차원 배열을 생성하려면 배열 변수 선언 시 타입 뒤에 대괄호 [] 를 차원의 수만큼 붙이고, 값 목록도 마찬가지로 차원의 수만큼 중괄호를 중첩시킴

package ch05.sec07;

import javax.annotation.processing.SupportedSourceVersion;

public class MultidimensionalArrayByValueListExample {

	public static void main(String[] args) {
		//2차원 배열 생성
		
		int[][] scores = {
				{80,90,96},
				{76,88}
		};
		
		
		
		//배열의 길이
		System.out.println("1차원 배열 길이(반의 수): " + scores.length);
		System.out.println("2차원 배열 길이(첫 번째 반의 학생수): " + scores[0].length);
		System.out.println("2차원 배열 길이(두 번째 반의 학생수): " + scores[1].length);
		
		//첫 번째 반의 세번째 학생의 점수 읽기
		System.out.println("scores[0][2]: " + scores[0][2]);
		
		//두 번째 반의 두번째 학생의 점수 읽기
		System.out.println("scores[1][1]: " + scores[1][1]);
		
		
		//첫 번째 반의 평균 점수 구하기
		int class1Sum =0;
		for(int i=0; i<scores[0].length; i++) {
			class1Sum += scores[0][i];
			
		}
		double class1Avg =(double) class1Sum/scores[0].length;
		System.out.println("첫 번째 반의 평균 점수: "+class1Avg);
		
		//두 번째 반의 평균 점수 구하기
		int class2Sum=0;
		for(int i=0;i<scores[1].length;i++) {
			class2Sum += scores[1][i];
		}
		double class2Avg =(double) class2Sum/scores[1].length;
		System.out.println("두 번째 반의 평균 점수: " + class2Avg);
		
		//전체 학생의 평균 점수 구하기
		int totalStudent=0;
		int totalSum=0;
		
		for(int i=0; i<scores.length;i++) {
			totalStudent += scores[i].length;
			for(int k=0;k<scores[i].length;k++) {
				totalSum+=scores[i][k];
			}
		}
		double totalAvg=(double)totalSum/totalStudent;
		System.out.println("전체 학생의 평균 점수: " + totalAvg);
	}

}
===================================================================
콘솔 출력문
===================================================================
1차원 배열 길이(반의 수): 2
2차원 배열 길이(첫 번째 반의 학생수): 3
2차원 배열 길이(두 번째 반의 학생수): 2
scores[0][2]: 96
scores[1][1]: 88
첫 번째 반의 평균 점수: 88.66666666666667
두 번째 반의 평균 점수: 82.0
전체 학생의 평균 점수: 86.0

new 연산자로 다차원 배열 생성

 new 연산자로 다차원 배열을 생성하려면 배열 변수 선언 시 타입 뒤에 대괄호 [] 를 차원의 수만큼 붙이고, new 타입 뒤에도 차원의 수만큼 대괄호 [] 를 작성하면 됨.

타입[][]변수 = new 타입[1차원수][2차원수];
  • 항목의 값은 초기값을 갖게 됨. 정수 타입은 0, 실수 타입은 0.0, 논리 타입은 false, 참조 타입은 null
package ch05.sec07;

public class MultidimensionalArrayBynewExample {
	public static void main(String[] args) {
		// 각 반의 학생 수가 3명ㅇ로 동일할 경우 점수 저장을 위한 2차원 배열 생성
		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();
		// 배열 항목 값 변경
		mathScores[0][0] = 80;
		mathScores[0][1] = 83;
		mathScores[0][2] = 85;
		mathScores[1][0] = 86;
		mathScores[1][1] = 90;
		mathScores[1][2] = 92;

		// 전체 학생의 수학 평균 구하기
		int totalStudent = 0;
		int totalMathSum = 0;

		for (int i = 0; i < mathScores.length; i++) { // 반의 수만큼 반복
			totalStudent += mathScores[i].length; // 반의 학생 수 합산
			for (int k = 0; k < mathScores[i].length; k++) { // 해당 반의 학생 수 만큼 반복

				totalMathSum += mathScores[i][k];
			}
		}
		double totalMathAvg = (double) totalMathSum / totalStudent;
		System.out.println("전체 학생수의 수학 평균 점수: " + totalMathAvg);
		System.out.println();

		// 각 반의 학생 수가 다를 경우 점수 저장을 위한 2차원 배열 생성
		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();

		// 배열 항목 값 변경

		englishScores[0][0] = 90;
		englishScores[0][1] = 91;
		englishScores[1][0] = 92;
		englishScores[1][1] = 93;
		englishScores[1][2] = 94;

		// 전체 학생의 영어 평균 구하기
		totalStudent = 0;
		int totalEnglishSum = 0;
		for (int i = 0; i < englishScores.length; i++) {
			totalStudent += englishScores[i].length;
			for (int k = 0; k < englishScores[i].length; k++) {

				totalEnglishSum+=englishScores[i][k];
			}
			double totalEnglishAvg=(double) totalEnglishSum/totalStudent;
			System.out.println("전체 학생의 영어 평균 점수: "+ totalEnglishAvg);
		}
	}

}
=====================================================================================
콘솔 출력문
=====================================================================================
mathScores[0][0]: 0
mathScores[0][1]: 0
mathScores[0][2]: 0
mathScores[1][0]: 0
mathScores[1][1]: 0
mathScores[1][2]: 0

전체 학생수의 수학 평균 점수: 86.0

englishScores[0][0]: 0
englishScores[0][1]: 0
englishScores[1][0]: 0
englishScores[1][1]: 0
englishScores[1][2]: 0

전체 학생의 영어 평균 점수: 92.0

객체를 참조하는 배열

기본 타입(byte, char, short, int, long, float, double, boolean) 배열은 각 항목에 값을 직접 저장

참조 타입(클래스, 인터페이스) 배열은 각 항목에 객체의 번지를 저장

객체 참조 배열의 메모리 구조

package ch05.sec08;

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

}
=============================================================
콘솔 출력문
=============================================================
true
false
true
  • 객체 참조 배열 내에 요소들은 모두 String 객체에 Java를 대입
    • 인덱스 0, 1 에는 대입을 통한 String 객체 생성으로 값이 동일하면 번지수까지 동일
      • 인덱스 2는 new 연산자를 통한 String 객체 생성으로 값이 동일하여도 번지수는 다름

배열 복사

배열은 한 번 생성하면 길이를 변경할 수 없음

더 많은 저장 공간이 필요하다면 더 큰 길이의 배열을 새로 만들고 이전 배열로부터 항목들을 복사해야 함

가장 기본적인 복사 방법은 for문을 이용해서 항목을 하나씩 읽고 새로운 배열에 저장하는 것

package ch05.sec09;

public class ArrayCopyByForExample {

	public static void main(String[] args) {
		// 길이 3인 배열
		int[] oldIntArray = { 1, 2, 3 };

		// 길이 5인 배열을 새로 생성
		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,0,0,
  • 복사 되지 않은 인덱스 3,4 항목은 초기값인 0을 유지

 두번째 방법은 System 의 arraycopy() 메서드를 이용하기

System.arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
  • Object src는 원본배열
  • int srcPos 는 원본 배열 복사 시작 인덱스
  • Object dest 는 새배열
  • int destPos 는 새 배열 붙여넣기 시작 인덱스
  • int length 는 복사 항목수
package ch05.sec09;

public class ArrayCopyExample {

	public static void main(String[] args) {
		
		//길이 3인 배열
		String[] oldStrArray = {"java","array","copy"};
		// 길이 5인 배열 새로 생성
		String[] newStrArray = new String[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,
  • String 은 초기값이 null 이므로 복사되지 않은 인덱스 3,4번 항목은 null 을 유지하고 있으며 항목의 값이 String 객체의 번지이므로 번지 복사가 되어 참조하는 String 객체는 변함이 없다

배열 항목 반복을 위한 향상된 for 문

자바는 배열 및 컬렉션을 좀 더 쉽게 처리할 목적으로 카운터 변수와 증감식을 사용하지 않고, 항목의 개수만큼 반복한 후 자동으로 for 문을 빠져나가는 향상된 for문을 사용할 수 있다.

for 문이 실행되면 ①배열에서 가져올 항목이 있을 경우 ②변수에 항목을 저장하고, ③실행문을 실행

다시 반복해서 ①배열에서 가져올 다음 항목이 존재하면 ② -> ③-> ① 로 진행, 가져올 항목이 없으면 for문을 종료

package ch05.sec10;

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

}
====================================================
콘솔 출력문
====================================================
점수 총합 = 430
점수 평균 = 86.0

main() 메소드 String[] 매개변수 용도

자바 프로그램을 실행하기 위해 지금까지 main() 메소드를 작성, 여기서 문자 배열 형태인 String[] args 매개 변수가 왜 필요할까?

package ch05.sec11;

public class MainStringArrayArgument {

	public static void main(String[] args) {
		if(args.length != 2) {
			System.out.println("프로그램 입력값이 부족");
			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);
	}

}
===================================================================
콘솔 출력문
===================================================================
그냥 실행시: "프로그램 입력값이 부족"
-------------------------------------------------------------------
run->run configurations-> arguments 에서 Program argument 에 10 20 을 넣고 run 실행시
10+20=30
  • 자바에서 main() 메소드의 String[] 매개변수는 프로그램 실행 시 커맨드 라인에서 전달되는 인수(arguments)를 받기 위한 것
  • 이를 통해 사용자는 프로그램의 동작을 외부에서 제어하거나 데이터를 입력

열거(Enum) 타입

데이터 중에는 몇 가지로 한정된 값을 갖는 경우가 있음

예를 들어 요일은 월,화,수,목,금,토,일 이라는 7개 값을 계절은 봄, 여름, 가을 ,겨울 이라는 4개의 값을 갖음

이와 같이 한정된 값을 갖는 타입을 열거타입(enumeration type) 이라고 함

 

열거타입을 사용하기 위해서는 열거 타입 이름으로 소스파일(.java) 를 생성하고 한정된 값을 코드로 정의해야함

열거타입 이름은 첫 문자를 대문자로하고 캐멀스타일로 지어주는 것이 관례

 

이클립스에서 Enum 파일 생성방법 예시

1. Package Explorer 에서 마우스 우측버튼 클릭 후 [New] -> [Enum]

2.[New Enum Type] 대화 상자에서 Name 입력란에 'Week' 이라 입력하고 Finish

3. 열거 상수 목록을 작성

  • 열거 상수는 열거 타입으로 사용할 수 있는 한정된 값을 의미
  • 관례적으로 알파벳으로 정의, 모두 대문자로 작성
  • 만약 열거 상수가 여러단어로 구성될 경우는 언더바(_) 로 연결한다
package ch05.sec12;

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

}

 

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

열거 타입 변수에는 열거 상수를 대입할 수 있고 [열거타입.열거상수] 형태로 작성

열거 타입은 참조 타입이므로 변수에 null 도 대입할 수 있음

열거 변수의 값이 특정 열거 상수인지 비교할 때는 == 와 != 연산자를 사용

package ch05.sec12;

import java.util.Calendar;

public class WeekExample {

	public static void main(String[] args) {
		//Week 열거 타입 변수 선언
		Week today=null;
		
		//Calendar 얻기
		//컴퓨터 날짜 및 시간 정보를 가진 Calendar 객체를 얻고 번지를 cal 변수에 대입
		Calendar cal= Calendar.getInstance();
		
		//오늘의 요일 얻기(1~7)
		//DAY_OF_WEEK 은 일(1)~토(7) 까지의 숫자를 얻는것.
		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;
		}
		//열거 타입 변수를 사용
		
		if(today==Week.SUNDAY) {
			System.out.println("일요일에는 축구를 합니다.");
		} else {
			System.out.println("열심히 자바를 공부합니다.");
		}
		
	}

}