본문으로 바로가기

[JAVA ] 참조 타입(배열)

category Java 2022. 1. 31. 01:46
  • 배열은 많은 양의 데이터를 적은 코드로 처리할 수 있다.

ex) 학생 30명의 성적을 저장하고 평균값을 구하려면?

int score1 = 90;
int score2 = 80;
int score3 = 85;
.....
int score30 = 75;

int sum = score1;
sum += score2;
sum += score3;
...
sum += score30;
int avg = sum / 30; //좋지 못한 방법 코드가 길어짐

배열을 사용하지 않고 코드를 작성하면 위와 같이 코드가 길어짐

 

배열

  • 데이터를 연속된 공간(메모리)에 나열하고 각 데이터에 인덱스 부여한 자료구조
  • 인덱스:0 부터 시작해 0~(배열길이 -1)까지 범위 가짐
  • 같은 타입의 데이터만 저장할 수 있음
  • 한번 생성된 배열은 길이를 늘리거나 줄일 수 없음
  • score 배열 

 

위와 같이 만들면 for문을 이영한 배열처리가 쉬워짐.

ex) 학생 30명의 성적을 저장하고 평균값을 구하려면?

int sum = 0;
for(int i=0; i<30; i++) {
	sum += score[i];
}
int avg = sum / 30;

for는 점수의 갯수만큼만 돌면 됨

배열의 대괄호에 [인덱스]를 주게 되면 인덱스의 해당 값을 읽을 수 있음

즉 30개의 점수가 전부 sum에 누적됨

sum(30개의 점수를 모두 더한값)을 30으로 나누면 평균값이 도출됨

 

배열 변수 선언

int[] intArray;
double[] doubleArray;
String [] strARRAY;
// 첫번째 방법: 타입 뒤에 대괄호를 넣고 변수명을 선언하는 방법(보통 많이씀)

int intArray[];
double doubleArray[];
String strArray[];
// 첫번째 방법: 변수명에 대괄호를 붙이고 변수명을 선언하는 방법
  • 배열을 선언하기 위해서는 타입 뒤에나 변수 이름 뒤에 대괄호를 붙이면 됨.
  • 보통은 타입 뒤에 대괄호를 붙여 선언하는 경우가 많음
  • 즉, 타입[] 변수; 형태로 선언
  • 배열은 참조 타입이기 때문에 선언된 변수에는 배열의 번지가 저장됨
  • 아직 배열이 없다면 null 값으로 초기화

 

  • 참조할 배열 객체 없는 경우 배열 변수는 null 값으로 초기화한다.
타입[] 변수 = null;

변수를 선언하고 null을 초기값으로 대입할 수 있음

 

배열 생성

  • 값 목록으로 배열을 생성하는 방법과 new 연산자를 이용해서 배열을 생성하는 방법이 있음

값 목록으로 배열 생성

  • 중괄호를 사용
  • { 값1, 값2, 값3, ...} 과 같이 값 목록으로 생성
  • 중괄호에 값 목록을 작성하면 자바는 이것을 배열로 생성시키고 그 번지를 앞에 변수에 저장을 시켜줌
타입[] 변수 = { 값0, 값1, 값2, 값3, ...};

값 목록으로 생성할 경우 중괄호 사이의 값들을 배열로 생성한 후 그 번지를 변수에 저장한다.

 

new 연산자를 이용해서 배열 생성

  • new 키워드 뒤 타입이 오고 그 뒤에 대괄호 안에 배열의 길이가 온다.
  • new 타입[길이]; 로 생성
int[] scores = new int[30];

생성된 배열의 번지가 scores에 저장

 

 

값 목록을 이용해서 배열 생성

타입[] 변수 = { 값0, 값1, 값2, 값3, ...};

자바는 이 값의 리스트를 가지고 배열을 만듦 다시말해 힙 영역에 배열 객체를 만듦

int[] scores = {90, 95, 87, 93, ...};

 

  • 배열 변수 선언한 후에 그 밑에 다른 실행문에서 값 목록으로 배열 생성 불가능
타입[] 변수;
변수 = {값0, 값1, 값2, 값3, 값4...}; //컴파일 에러

 

  • 배열 변수 미리 선언한 후 값 목록이 나중에 결정되는 경우
    • new 연산자 사용하여 값 목록 지정
변수 = new 타입[] {값0, 값1, 값2, 값3, ...};​
String[] names = null;
names = new String[] {"신용권", "홍길동", "김자바"};

 

new 연산자로 배열 생성

타입[] 변수 = new 타입[길이];
  • 배열 변수가 선언된 경우
타입[] 변수 = null;
변수 = new 타입[길이];
  • new 연산자로 배열 처음 생성할 때 배열은 자동적으로 기본값으로 초기화가 된다.
    • int 배열
      • 기본값으로는 0이저장
int [] scores = new int[30];

위에서 아래 해당부분은 배열 생성 후 특정 인덱스 위치에 새 값 저장하는 방법이다.

  • String 배열
    • 기본값으로는 null이저장
String[] names = new String[30];

  • double 배열
    •  기본값으로는 0.0이 저장

 

배열 길이

  • 배열에 저장될 수 있는 항목의 수 (배열변수.length )
  • 배열에 저장할 수 있는 전체 요소 수
  • intArray.length
int[] intArray = {10, 20, 30};
int num = intArray.length;

 

값 목록의 갯수 대신에 배열의 길이인 .length를 넣을 수 있음

 

main() 메소드의 String[] args 매개 변수

  • 실행할 때 명령라인 매개값을 주지 않았을 경우
    • 길이0인 sting 배열 생성 후 main 메소드 호출
    • 길이가 0이다 => 요소가 없다

 

main() 메서드에 args 배열의 요소가 비어있어 main 메서드 호출 시 길이 0인 String배열이 생성

  • 실행할 때 명령라인 매개 값을 주었을 경우

위의 상태에서 main메서드의 매개 값을 줄 때

 

 Run Configurations클릭

 

Arguments 탭에서 문자열을 입력

 

실행 매개값 사이에는 공백으로 구분

3개의 매개값이 들어갔다.

  • System.exit(0)

 

 

 

2차원 배열

  • 타입[][] 변수=new타입[길이1][길이2]; 로 생성
  • 수학의 행렬과 같은 구조로 가로와 세로로 표가 만들어진다고 생각하면 쉽게 접근 가능

int[][] scores = new int[2][3];   // 2 * 3 표 모양의 행렬 생성
  • 실제로 자바가 표와 같은 형태로 2차원 행렬 데이터를 저장하지는 않음
  • 구현방법 : 1차원 배열이 다시 1차원 배열을 참조하여 다차원 배열을 만듦

scores.length //2(배열 A의 길이)
scores[0].length //3(배열 B의 길이)
scores[1].length //3(배열 C의 길이)

scores의 length: 처음 행의 길이(2)

scores[0], scores[1]의 길이: 그 행이 참조하고 있는 열의 길이(3)

 

  • 계단식 구조
    • 자바는 1차원 배열을 연결하여 다차원 배열을 만들기 때문에 계단식 구조도 만들 수 있음
int[][] scores = new int[2][]; //처음엔 행 수만을 입력하고 열의 값을 비워둔다. 
scores[0] = new int[2];  // 0번 째 인덱스에 2칸의 행렬을 대입한다
scores[1] = new int[3];   //1번 째 인덱스에 3칸의 행렬을 대입한다

  • 값 목록을 이용한 2차원 배열 생성
타입[][] 변수 = { {값1, 값2, ...}, {값1, 값2, ...}, ...};  //중괄호 블럭의 개수가 행 수, 블럭 내 요소의 개수가 열 수가 된다.
int[][] scores = { {95,80}, {92, 96} };
int score = scores[0][0]; //95
int score = scores[1][1]; //96
int[][] mathScores = new int[2][3];
for(int i=0; i<2; i++)
{
	for(int k=0; k<3; k++)
    {
		System.out.println("mathScores[" + i + "][" + k + "]=" + mathScores[i][k]);
	}
}

2차원 배열의 요소를 출력하기 위해서는 중첩된 for문을 사용

계단식 배열에서의 출력 시

위에 코드에서는 0행에는 2칸의 열을 만들었고, 1행에는 3칸의 열을 계단식으로 만들었다.

이때 안쪽의 for문 반복 조건을  k<3까지 반복하라는 명령을 주었는데

0행에는 열의 개수가 2개밖에 없기 때문에 위와 같이 코드가 정상적으로 출력이 되지 않는다.

 

 

안쪽 for문의 조건문에 k<3이 아니라 englishScores의 행 길이를 변숫값으로 주면 정상적으로 출력할 수 있다.

 

값의 목록을 지정해 줬을 때

이때 중괄호 블록의 개수가 행의 개수가 되고 중괄호 내의 요소의 개수가 열의 개수가 된다

위 코드에서는 1행의 요소를 2개를 주고 2행의 요소를 3개를 주어 계단식 배열을 만들었다.

 

참조 타입 배열

    • 기본 타입이 아닌 참조 타입의 배열은 요소의 값(리터럴)을 저장하지 않고, 객체의 번지를 저장을 한다.
    • 예를 들어 String 배열 변수를 선언 할 때 (String은 참조 타입 중 클래스에 해당함)
String[] strArray = new String[3]; 
strArray[0] = "Java"; 
strArray[1] = "Java"; 
strArray[2] = new String("java");​

strArray 변수에 3개의 배열 객체를 만들어 대입하고 각 인덱스에 "Java" 문자열을 추가해주면 메모리에 아래 그림처럼 생성이 된다.

이때 0과 1인덱스에서는 힙 영역에 생성된 동일한 "Java" String 객체를 공유하여 참조한다.

2인덱스에서는 new연산자를 사용하여 새로운 "Java" String 객체를 만들었기에 다른 번지에서 생성된 "Java" 객체를 참조하게 된다.

 

 

System.out.println( strArray[0] == strArray[1]);       //true  (번지 비교)
System.out.println( strArray[0] == strArray[2]);       //false (번지 비교)
System.out.println( strArray[0].equlas(strArray[2]) ); //true  (문자열 비교)

여기서 각 객체를 비교하게 되면 인덱스 0과 1은 같은 번지를 참조하고 있어 true를 출력하고

인덱스 0과 2는 서로 다른 번지를 참조하고 있어 false를 출력하게 된다.

하지만 .equals 연산자는 번지가 아닌 문자열 그 자체를 비교하게 되어 true를 출력한다.

 

 

배열 복사

  • 배열복사란 기존의 배열을 복사하여 새로운 배열을 만드는 것
  • 배열은 한번 길이가 정해지면 바꿀 수 없어서 추가적인 요소를 저장하려면 배열 복사를 하여 새로운 배열을 만들어야 하는데 이때 배열 복사가 필요하다.
  • for문을 이용해서 요소 하나하나를 복사 하는 방법과 System.arraycopy()를 이용한 복사가 있다.
  • for문을 이용한 방법

for문 조건문에 length속성을 이용하여 비어있는 newIntArray 배열에 oldIntArray를 복사하여 출력시킴

 

  • System.arraycopy()를 이용한 방법
System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);
//                원본 배열  /  인덱스   /   대상 배열   /  인덱스   /  개수
//원본 배열 , 인덱스 : 원본배열에서 어디서부터 복사할 것인가 , 대상배열, 인덱스: 대상배열에서 어디서부터 복사할거냐,원본배열 몇개를 복사할거냐
String[] oldStrArray = {"java", "array", "copy"};
String[] newStrArray = new String[5]'

위 oldStrArray 배열변수에 추가적인 2개의 요소를 집어넣으려면 아래와 같은 코드를 호출한다.

 

System.arraycopy(oldStrArray, 0, newStrArray, 0 , oldStrArray.length);

첫 번째 인자 : oldStrArray (어떤 배열을 복사할 것인가)

두 번째 인자 : 0 (어디서부터 복사를 할 것인가.

세 번째 인자 : newStrArray (어떤 배열에 붙여 넣을 것인가)

네 번째 인자 : 0 (대상의 배열에 어디부터 붙여 넣을 것인가)

다섯 번째 인자 : oldStrArray.length (몇 개를 복사할 것인가, length속성을 사용하여 원본 배열의 길이만큼 복사)

 

 

향상된 for문

  • 배열요소를 처음부터 쉽게 일괄처리 하기 위해 사용
  • for(타입변수 : 배열) {...}
  • 배열에 있는 인자들을 하나 씩 실행해주는 for문(for문은 배열의 요소수만큼 반복을 하다 빠져나오게 됨)
  • 배열이나 컬렉션을 좀 더 쉽게 처리 (초기화식, 조건식, 증감식 없음)
  • 반복 실행 위해 루프 카운터 변수나 증감식 사용하지 않음

scores 배열에 인자를 하나씩 score 변수에 대입하여 sum에 저장하는 코드이다.

 

평균값 출력 예시 (실수 타입 계산에는 정수를 꼭 double 타입 형 변환 해주는걸 잊지 말자)

 

열거타입

  • 데이터 중에는 몇 가지를 한정된 값만을 갖는 경우가 있음
  • ex) 4계절 : 봄, 여름, 가을, 겨울 /ex) 달력 : 1월, 2월, 3월... ,12월 /ex)요일 :월, 화, 수, 목, 금, 토, 일  등이 있다.
  • ( int 나 sting은 열거타입이 아님. int는 정수값이면 다 줄수있고 sting도 문자열이면 다 저장될수 있으므로)
  • 이러한 한정된 값을 갖는 타입을 열거 타입이라고 함
  • 열거 상수(한정된 값)를 저장하는 타입
  • 자신이 선언한 열거 상수만을 저장함

 

위와 같이 Week 열거 타입을 선언하면 해당 타입으로는 선언된 상수만을 사용할 수 있게 된다.

Week today;
today = Week.FRIDAY;

 

열거 타입 선언

  • 소스파일(.java) 생성
  • 열거 타입 선언 
public enum 열거타입이름 { ... }

열거타입은 enum 을 선언한다. ( 클래스 만들땐 public class 열거타입 만들땐 class 대신 enum)

public enum Week {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}
    // (열거타입 이름) /              열거 상수
  • 관례적으로 열거 상수는 전부다 대문자로 표현한다.

  • 열거 상수는 열거 객체로 생성되어 위와 같은 형식으로 메모리(힙 영역)에 저장
  • 열거 타입도 참조 타입

 

열거 타입 변수 선언

  • 열거타입 선언이 되면 열거타입 변수를 선언해 줄 수 있게 된다.
열거타입 변수;

위와같이 열거타입 언급을 해주고 뒤에 변수명을 작성해주면 됨

Week today;             //Week라는 열거타입으로 today 라는 변수를 선언해줌
Week reservationDay;    //Week라는 열거타입으로 reservationDay 라는 변수를 선언해줌

위와 같은 변수를 Week 열거 타입으로 선언하게 되면 위 변수에는 열거 상수를 저장할 수 있게 된다.

 

열거 상수 저장

열거타입 변수 = 열거타입.열거상수;

열거타입의 변수가 위와같이 선언이 되어있을 경우 해당 열거타입의 상수를 변수에 대입 할 수 있다.

Week today = Week.SUNDAY;
today == Week.SUNDAY;  //true

위크타입에 투데이 변수를 선언하고 여기에 위크타입이 가지고있는 열거상수인 SUNDAY를 대입을  할 수 있다.

 

메서드 영역에 있는 SUNDAY 열거 상수가 힙 영역에 생성되어 있는 Week(참조타입) 열거 객체를 참조하고

Week 열거 타입으로 선언한 스택 영역에 있는 today 변수에 열거 상수 SUNDAY를 저장하면

Week 열거 객체를 참조하게 되어 SUNDAY가 참조하는 객체와 today가 참조하는 객체의 번지는 같다.

 

Week 라고 하는 변수 today를 선언하고 내가 값으로 week.SUNDAY 를 저장했다. 

그러니 today에 저장되어있는 값은  week.SUNDAY 랑 같을 수 밖에 없다.

 

  • week라고 하는 열거 타입에 어떤 변수에 아직  객체 참조가 없다는 뜻에서 다음과 같이 null을 저장할 수 있다.
Week birthday = null;

열거 타입 또한 참조 타입이므로 위와 같이 열거 변수의 저장 값으로 null을 줄 수도 있다. 

 

 

 

혼자공부하는자바


코딩 공부하는 블로그
블로그 이미지 서하현 님의 블로그
VISITOR 오늘 / 전체