[til_211126][java] 객체배열

2021. 11. 26. 14:09JAVA

�오늘의 궁금증 ↓더보기 클릭

더보기

�오늘 궁금증:

* 왜 main 이 아닌 클래스에서 배열을 생성하면 오류가 발생하는가? 여기서 오류는,,, 직접적인 오류가 아니라 약간 다른 데서 이상하게 튕기듯이? 오류가 나타남. 

이렇게 생성한 두줄 전체에 빨간 줄이 그어지는 오류가 아니라, 저렇게 ;에 빨간 줄이 그어짐.. 어떻게 생성때문인 줄 알았냐면 배열 생성하는 저 두 줄을 지우면 또 빨간 줄 사라짐.사실 이게 정확한 원인이 뭔지는 모르겠다.main이 아닌 클래스에서는 배열을 생성하지 못하는 건가...? 

해결   일단 객체 배열의 개념을 완전 오해함. 객체 배열은 객체 여러개를 배열로 저장하는 것이지, 배열을 지닌 객체를 만드는 것이.. 아니다.. 근데 그렇다 하더라도 그럼 클래스를 만들 때 그 안에 일반 기본형 배열은 못 만드는 것인가? 아니, 객체 배열이 있으니까 그럴 필요가 없는 건가? 아마 그런 것 같다. 

 

객체 배열 : 그 동안 객체 배열을 완전 오해했다. 

잘못 이해해서 나는 객체배열이 객체에 인자를 전달할 때 배열을 인자로 전달하는 건 줄 알았는데

객체배열이란, 여러개의 객체를 생성할 때 배열로써 생성하는 것. 그러니까 여러 객체로 이루어진 배열임.!!

그런데 일반 기본형 배열을 만들 때와 약간의 차이가 있다.

 

< cf. 기본형 배열을 만드는 과정: >1) 배열 선언  -- int[] myArray;    :: 실제 저장공간 확보한 것이 X. 저장할 위치정보만 선언한 것 O. 즉 'myArray라는 위치에 배열을 만들 거야~' 정도.2) 배열 생성  -- myArray = new int[5];    :: 실제 저장공간 확보 O. 즉 myArray 위치에다가 원소 5개, 즉 크기가 5인 저장공간을 생성한 것!

 

< 객체 배열을 만드는 과정: >1) 레퍼런스 변수 선언  -- Circle[] c;     :: Circle은 객체를 찍어낼 클래스 이름. c는 레퍼런스 변수로, 기본형 배열 선언과 마찬가지로 위치정보만 선언한 것.2) 레퍼런스 배열 생성  -- c = new Circle[5];    ::여기서 기본형 배열 생성 단계와 차이 있음 - 아직 저장공간 확보한 것 X. 그냥 연결될 객체의 위치를 가리킬 수 있는 상태인 것 ! 여기선 '5개의 객체를 만들거야 ~ 각 객체는 이 곳(c[0] ~ c[4]) 에 연결될거임 ~ ' 정도.3) 배열의 각 원소 객체 생성  -- for ( int i =0 ; i < c.length ; i++) { c[i] = new Circle(i); }   :: 여기까지 해야 저장공간 확보 O. 레퍼런스 배열 각 원소 위치에 객체 배열 연결. 즉 여러 객체가 배열의 원소로 저장됨. ==> 객체 배열. 

(여기서 Circle클래스의 생성자는 Circle(int radius) { this.radius = radius; } 임. 즉 각기 다른 radius값을 가진 객체들이 배열로 생성되는 것임.)

 

 

* 일반 기본형 배열을 만들 때 int[] myArray = new int [5]; 처럼 선언과 생성을 한 줄로 합칠 수 있는 것처럼 객체 배열을 만들 때도 Circle[] c = new Circle[5]; 로 '레퍼런스' 배열 선언과 생성을 한 줄로 합칠 수 있다. 즉 int등 배열 type 자리에 클래스 이름을 대체해 넣으면 됨. 단, 객체 배열의 경우 여기서 한 단계가 더 추가되는 것임.


✍ Book 배열 (객체 배열) 을 만들고 각 원소로 Book의 객체 book들을 만들어 저장해 놓는 예제 :

class Book {
	private String title, author;

	Book(String title, String author) {
		this.title = title;
		this.author = author;
	}

	String getTitle() {
		return title;
	}

	String getAuthor() {
		return author;
	}

	void setTitle(String title) {
		this.title = title;
	}

	void setAuthor(String author) {
		this.author = author;
	}
}

Book 클래스에서 setTitle setAuthor 메소드는 setter 개념 이해 위해서 만들어 놓은 거라 없다고 생각해도 된다. 

import java.util.Scanner;

public class Main {		
    public static void main (String args[]) {
    	Scanner sc = new Scanner(System.in); 
    	Book[] book = new Book[500];    //'레퍼런스'배열 생성. 아직 객체배열 저장공간 확보는 x. 객체 생성 아님 !
    	int size=0;  // 실제 저장된 유효 저장공간 크기. (배열 크기가 500이더라도 실제 저장된 공간은 그보다 작을 수 있으므로.)
    	String title = "", author;
    	
    	while ( !title.equals("끝") ) {    // break조건: 제목이 "끝"
    		System.out.print("제목 입력: ");
        	title = sc.nextLine();
        	System.out.print("저자 입력: ");
        	author = sc.nextLine();
        	book[size] = new Book(title, author); // 객체 생성: book[size]위치에 연결될 새로운 객체를 new 로 생성자와 함께 생성. 
        	size ++;
    	}
    	
    	for (int i=0; i<size-1; i++) {
    		System.out.println("[ "+book[i].getTitle()+", "+book[i].getAuthor()+" ]");
    	}
  }
}

 

✔ int size 로 실제 저장된 유효 저장공간 크기 나타내는 변수 설정해두기: 레퍼런스 배열 선언, 생성하면서 설정해 둔 크기는 전체 크기이지만, 꼭 그 저장공간을 가득 채워서 객체를 저장하지는 않기 때문에 실제로 저장된 공간의 사이즈를 나타내는 변수를 설정해두는 것임. 

✔ 객체 생성은 book[인덱스] = Book(생성자); 의 단계에서 이루어진다. 레퍼런스 배열을 선언하고 생성할 때는 말 그대로 레퍼런스만 배열로 만드는 것이고, 아직 각각에 연결되는 객체는 안 만들어짐. !!!!! ⛧⛧⛧

 


✍ King 클래스의 객체들을 배열로 저장하는 예제. King 클래스는 왕의 이름과 즉위 순서를 저장하는 클래스임.

class King {
	private String name;
	private int order;
	
	King(String name, int order) {
		this.name = name;
		this.order = order;
	}

	void show() {
		System.out.println("조선 "+order+"대 왕 "+name);
	}
}
import java.util.Scanner;

public class Main {		
    public static void main (String args[]) {
    	Scanner sc = new Scanner(System.in); 
    	
    	King[] king = new King[30];
    	String name = "";
    	int order = 0;
    	int size = 0;
    	menu();
    	
    	int n = 90;
    	while (n!=0) {
        	System.out.print("> ");
        	switch (n = sc.nextInt()) {
    		case 0:
    			System.out.println("종료되었습니다.");
    	    		break;  // get out of switch-case
    		case 1:
    			System.out.print("왕의 이름> ");
    			name = sc.next();
    			System.out.print("왕의 즉위 순서> ");
    			order = sc.nextInt();
    			king[size++] = new King(name,order);
    			break;
    		case 2:
    			for (int i =0; i<size; i++) {
    				king[i].show();
    			}
    			break;
    		case 3:
    			menu();
    		}
          }
     }
    
    static void menu() {
    	System.out.println("[ menu ]");
    	System.out.println("0 : exit");
    	System.out.println("1 : save info");
    	System.out.println("2 : read info");
    	System.out.println("3 : show menu");
    }
}

✔ 메인 코드에서 쓰인 'King' 과 'king[인덱스]' 구분하기 :

'King'은 클래스 이름이자 객체 배열 타입? 이라고 할 수 있음. 기본형 배열을 만들 때 int[] name = int[30], String[] name = String[4] 처럼 int, String, char 등의 배열 타입 (기본형 종류)을 써넣듯 객체 배열 만들 땐 배열 타입에다가 클래스 이름을 쓰는 것..

반면, 'king[배열의 인덱스]'는 그 배열의 각 원소로 존재하는 객체 하나하나임. 

 

✔ switch-case문에서 각 case문 끝에 break;를 꼭! 써줘야 다음 case로 자동으로 넘어가지 않고 switch-case문 빠져나갈 수 있음. if문 처럼 조건을 만족하는지 따지는 게 아니기 때문에..