ch06-object2 프로젝트의 kr.s09.abstracttest 패키지에 새 클래스 AbstractMain03 생성package kr.s09.abstracttest;
// 추상 클래스
abstract class AbsEx1 {
	// 필드
	int a = 100;
	int b = 200;
	final String STR = "abstract test"; // 문자열 상수
	// 일반 메서드
	public String getStr() {
		return STR;
	}
	// 추상 메서드
	abstract public int getA();
	public abstract int getB();
}
// 추상 클래스에 추상 클래스를 상속한 경우, 상속받은 추상 메서드를 구현하지 않아도 오류가 발생하지 않음
abstract class AbsEx2 extends AbsEx1 {
	// 필드
	String msg = "신세계";
	// 추상 메서드
	public abstract String getMsg();
	// 추상 메서드 구현
	@Override public int getA() {
		return a;
	}
}
// 일반 클래스에 추상 클래스를 상속한 경우, 상속받은 추상 메서드를 모두 구현해야 함
public class AbstractMain03 extends AbsEx2 {
	// 추상 메서드 구현
	@Override public int getB() {
		return b;
	}
	@Override public String getMsg() {
		return msg;
	}
	
	public static void main(String[] args) {
		AbstractMain03 ab = new AbstractMain03();
		System.out.println(ab.getA());
		System.out.println(ab.getB());
		System.out.println(ab.getStr());
		System.out.println(ab.getMsg());
	}
}
iterator()
java.util 패키지에 포함된 인터페이스hasNext()
true, 그렇지 않으면 false를 반환하는 메서드next()
remove()
next 메서드를 통해) 가장 마지막으로 반환된 요소를 Collection에서 제거하는 메서드ch09-collections 프로젝트의 kr.s01.list 패키지에 새 클래스 Product 생성package kr.s01.list;
public class Product {
	private String name; // 상품명
	private int price; // 상품 가격
	private String num; // 상품 번호
	private String maker; // 제조사
	private int stock; // 재고
	// Getters and Setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getPrice() {
		return price;
	}
	public void setPrice(int price) {
		this.price = price;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public String getMaker() {
		return maker;
	}
	public void setMaker(String maker) {
		this.maker = maker;
	}
	public int getStock() {
		return stock;
	}
	public void setStock(int stock) {
		this.stock = stock;
	}
}
ProductMain 생성package kr.s01.list;
import java.util.ArrayList;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class ProductMain {
	// 멤버 변수; list와 br을 생성자뿐만 아니라 멤버 메서드들에서 사용할 것이므로 멤버 변수로 선언해야 함
	ArrayList<Product> list;
	BufferedReader br;
	
	// 생성자
	public ProductMain() {
		list = new ArrayList<Product>();
		try {
			// 메뉴 메서드 호출 전에 입력 받을 수 있어야 함
			br = new BufferedReader(new InputStreamReader(System.in));
			// 객체가 생성되면 바로 메뉴 메서드 호출
			callMenu();
		}
		catch(Exception e) {
			// 콘솔에 예외 문구 표시
			e.printStackTrace();
		}
		finally {
			// 자원 정리; try~catch를 한 줄로 인식하므로 if문 블럭을 만들지 않아도 됨
			if(br!=null) try {br.close();} catch(IOException e) {}
		}
	}
	// 메뉴
	public void callMenu() throws IOException { // 입력 자체가 불가능한 경우는 종료
		while(true) {
			try {
				System.out.println("메뉴 : 1. 상품 입력, 2. 상품 목록 보기, 3. 종료");
				System.out.print("메뉴 > ");
				int num = Integer.parseInt(br.readLine());
				if(num == 1) {
					// 상품 입력 메서드 호출
					input();
				}
				else if(num == 2) {
					// 상품 목록 보기 메서드 호출
					output();
				}
				else if(num == 3) {
					System.out.println("프로그램 종료");
					break;
				}
				else {
					System.out.println("메뉴 번호를 잘못 입력하셨습니다.");
				}
			}
			catch(NumberFormatException e) { // 숫자를 입력하지 않은 경우는 while문을 반복하여 다시 입력하게 함
				System.out.println("숫자만 허용됩니다.");
			}
		}
	}
	
	// 상품 입력
	public void input() throws IOException {
		Product p = new Product();
		System.out.print("상품명 > ");
		p.setName(br.readLine());
		System.out.print("상품 번호 > ");
		p.setNum(br.readLine());
		System.out.print("상품 가격 > ");
		p.setPrice(Integer.parseInt(br.readLine())); // 가격의 경우 연산 가능성이 있으므로 String이 아니라 int로 입력받음
		System.out.print("제조사 > ");
		p.setMaker(br.readLine());
		System.out.print("재고 > ");
		p.setStock(Integer.parseInt(br.readLine()));
		
		// Product를 ArrayList에 저장
		list.add(p);
	}
	
	// 상품 목록 보기
	public void output() {
		System.out.println("상품명\t번호\t가격\t제조사\t재고");
		// ArrayList를 2차원 배열처럼 활용
		for(Product p : list) {
			System.out.printf("%s\t%s\t%,d원\t%s\t%,d개\n", p.getName(), p.getNum(), p.getPrice(), p.getMaker(), p.getStock());
		}
	}
	
	public static void main(String[] args) {
		// 객체가 생성되면 메뉴 메서드에서 작업을 수행하므로, main에서 작업을 진행하지 않으니 변수 선언할 필요도 없음
		new ProductMain();
	}
}
Member 생성
ctrl+2, r을 입력 후 변경하면 됨package kr.s01.list;
public class Member {
	/* [실습]
	 * 멤버 변수 : 이름(name), 나이(age), 직업(job), 주소(address), 전화번호(phone)
	 */
	private String name;
	private int age;
	private String job;
	private String address;
	private String phone;
	// Getters and Setters
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getJob() {
		return job;
	}
	public void setJob(String job) {
		this.job = job;
	}
	public String getAddress() {
		return address;
	}
	public void setAddress(String address) {
		this.address = address;
	}
	public String getPhone() {
		return phone;
	}
	public void setPhone(String phone) {
		this.phone = phone;
	}
}
MemberMain 생성package kr.s01.list;
import java.util.ArrayList;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class MemberMain {
	/*
	 * [실습]
	 * ArrayList, BufferedReader 생성
	 * 메뉴 : 1. 회원 정보 입력, 2. 회원 정보 출력, 3. 종료
	 */
	ArrayList<Member> ml;
	BufferedReader br;
	
	public MemberMain() {
		ml=new ArrayList<Member>();
		try {
			br=new BufferedReader(new InputStreamReader(System.in));
			callMenu();			
		}
		catch(IOException e) {
			e.printStackTrace();
		}
		finally {
			if(br!=null) try {br.close();} catch(IOException e) {}
		}
	}
	
	public void callMenu() throws IOException {
		while(true) {
			System.out.println("메뉴 : 1. 회원 정보 입력, 2. 회원 정보 출력, 3. 종료");
			System.out.print("메뉴 > ");
			String menu=br.readLine();
			if(menu.equals("1")) {
				setInfo();
			}
			else if(menu.equals("2")) {
				getInfo();
			}
			else if(menu.equals("3")) {
				System.out.println("프로그램이 종료되었습니다.");
				break;
			}
			else {
				System.out.println("번호를 잘못 입력하셨습니다.");
			}
		}
	}
	
	public void setInfo() throws IOException {
		Member m=new Member();
		System.out.print("이름 > ");
		m.setName(br.readLine());
		m.setAge(parseInputData("나이 > ")); // 나이 검증 메서드를 별도로 분리하여 호출
		System.out.print("직업 > ");
		m.setJob(br.readLine());
		System.out.print("주소 > ");
		m.setAddress(br.readLine());
		System.out.print("전화번호 > ");
		m.setPhone(br.readLine());
		ml.add(m);
	}
	
	// 입력값이 숫자인지 확인하고, 1 이상의 값만 입력받는 메서드
	public int parseInputData(String title) throws IOException {
		int a;
		while(true) {
			System.out.print(title);
			try {
				a=Integer.parseInt(br.readLine());
				if(a>=1) {
					break;
				}
				else {
					System.out.println("나이는 0 이하일 수 없습니다.");
				}
			}
			catch(NumberFormatException e) {
				System.out.println("나이는 숫자만 입력할 수 있습니다.");
			}
		}
		return a;
	}
	
	public void getInfo() {
		System.out.println("총 회원 수 : "+ml.size());
		if(ml.size()!=0) System.out.println("이름\t나이\t직업\t주소\t전화번호");
		for(Member m:ml) {
			System.out.println(m.getName()+"\t"+m.getAge()+"세\t"+m.getJob()+"\t"+m.getAddress()+"\t"+m.getPhone());
		}
	}
	
	public static void main(String[] args) {
		new MemberMain();
	}
}
java.util 패키지에 포함되어 있는 인터페이스로, Collection을 상속받음offer()
poll(), remove()
poll() 메서드는 null을 반환하고 remove() 메서드는 예외를 발생시킴peek(), element()
peek() 메서드는 null을 반환하고 element() 메서드는 예외를 발생시킴java.util 패키지에 포함되어 있는 클래스로, List와 Queue 인터페이스를 구현kr.s03.queue 생성하고 새 클래스 QueueMain 생성package kr.s03.queue;
import java.util.LinkedList;
public class QueueMain {
	public static void main(String[] args) {
		String[] array = {"서울", "인천", "광주", "부산", "대구"};
		LinkedList<String> ll = new LinkedList<String>();
		
		// ll에 offer() 메서드로 데이터 저장
		for(int i=0;i<array.length;i++) {
			ll.offer(array[i]);
		}
		System.out.println(ll);
		
		// ll에서 poll() 메서드로 데이터 꺼냄(=ll 안의 데이터는 지워짐)
		while(ll.peek()!=null) { // ll에 저장된 첫 번째 요소를 검색
			System.out.print(ll.poll() + "\t"); // ll에 저장된 첫 번째 요소를 반환하고 제거
		}
		System.out.println("\n"+ll);
	}
}
java.util 패키지에 포함되어 있는 인터페이스로, Collection을 상속받음java.util 패키지의 Iterator 인터페이스를 이용java.util 패키지에 포함되어 있는 클래스로, Set 인터페이스를 구현kr.s04.set 생성하고 새 클래스 HashSetMain01 생성package kr.s04.set;
import java.util.HashSet;
import java.util.Iterator;
public class HashSetMain01 {
	public static void main(String[] args) {
		String[] array = {"Java", "Oracle", "JSP", "Java", "HTML"};
		HashSet<String> hs = new HashSet<String>();
		
		// 데이터 저장
		for(String n : array) {
			hs.add(n); // 중복 불허; add() 메서드에서 걸러냄
		}
		System.out.println(hs); // 정렬을 보장하지 않음
		// 데이터 읽기; HashSet에서 바로 읽는 것이 아니라, Iterator로 복사해서 읽는 것이 원칙
		Iterator<String> ir = hs.iterator(); // iterator() 메서드로 HashSet의 데이터를 Iterator에 복사
		while(ir.hasNext()) { // hasNext() 메서드로 저장된 데이터가 있는지 확인
			System.out.println(ir.next()); // next() 메서드로 데이터를 꺼냄
		}
		
		System.out.println();
		
		// 확장 for문을 이용한 데이터 읽기
		for(String s : hs) {
			System.out.println(s);
		}		
	}
}
HashSetMain02 생성package kr.s04.set;
import java.util.HashSet;
import java.util.Random;
import java.util.Collections;
import java.util.ArrayList;
public class HashSetMain02 {
	public static void main(String[] args) {
		HashSet<Integer> set = new HashSet<Integer>();
		Random r = new Random();
		while(set.size()<6) {
			set.add(r.nextInt(45)+1); // 1~45 범위의 난수, 중복값 불허
		}
		System.out.println(set);
		
		ArrayList<Integer> list = new ArrayList<Integer>(set); // Collections.sort() 메서드는 List 인터페이스 자료형만 인자로 받기 때문에, ArrayList의 생성자를 통해 set의 데이터를 복사한 list를 생성
		Collections.sort(list);
		for(int num : list) {
			System.out.print(num + "\t");
		}
	}
}
java.util 패키지에 포함되어 있는 인터페이스,로 구분하여 명시put()
get()
null을 반환remove()
null을 반환keySet()
java.util 패키지에 포함되어 있는 클래스로, Map 인터페이스를 구현kr.s05.map 생성하고 새 클래스 HashMapMain01 생성package kr.s05.map;
import java.util.HashMap;
public class HashMapMain01 {
	public static void main(String[] args) {
		HashMap<String, Integer> mp = new HashMap<String, Integer>();
		
		// mp에 put() 메서드로 데이터 저장
		mp.put("너굴", 95);
		mp.put("콩돌", 100);
		mp.put("밤돌", 85);
		mp.put("링크", 93);
		mp.put("젤다", 70);
		mp.put("콩돌", 0); // Map 인터페이스는 식별자의 중복을 불허하며, 식별자가 중복되었을 경우 마지막에 등록한 값을 저장
		mp.put("가논", null); // 값으로 null 인정
		mp.put(null, 100); // 식별자로 null 인정
		System.out.println(mp);
		
		// get() 메서드에 식별자를 인자로 입력하여 연결된 값을 반환받음
		int num = mp.get("콩돌"); // Integer에서 int로 자동 변환 발생
		System.out.println("콩돌의 성적은 " + num);
		int nullnum = mp.get(null);
		Integer nullnum2 = mp.get("가논"); // int로 변수 선언시 Integer를 int로 변환하는 과정에서 예외 발생; 저장시에는 문제가 없어도 호출시 문제될 수 있으므로 조건문으로 null 제외하도록 검증하는 것이 안전
		System.out.println("식별자 null : " + nullnum + ", 값 null : " + nullnum2);
	}
}
HashMapMain02 생성package kr.s05.map;
import java.util.HashMap;
// import java.util.Set;
import java.util.Iterator;
public class HashMapMain02 {
	public static void main(String[] args) {
		String[] msg = {"Berlin", "Paris", "Seoul", "New York", "London"};
		HashMap<Integer, String> mp = new HashMap<Integer, String>();
		// 반복문을 통해 데이터 저장
		for(int i=0;i<msg.length;i++) {
			mp.put(i, msg[i]);
		}
		System.out.println(mp);
		
		// 식별자를 모두 추출하고, 식별자를 통해 값을 읽기; keySet() 메서드를 통해 Set 인터페이스를 구현한 객체로 복사 후, iterator() 메서드를 통해 Iterator 객체로 복사해야 함
		Iterator<Integer> keys = mp.keySet().iterator(); // mp.keySet()은 Set 인터페이스 자료형
		while(keys.hasNext()) {
			Integer key = keys.next();
			System.out.println(key + ", " + mp.get(key));
		}
	}
}
java.util 패키지에 포함되어 있는 클래스로, Map 인터페이스를 구현keys()
HashtableMain 생성package kr.s05.map;
import java.util.Hashtable;
import java.util.Enumeration;
public class HashtableMain {
	public static void main(String[] args) {
		Hashtable<String, String> h = new Hashtable<String, String>();
		
		// h에 put() 메서드로 데이터 저장
		h.put("name", "홍길동");
		h.put("age", "20"); // 값의 자료형을 String으로 지정했기 때문에 10 입력시 예외 발생
		h.put("tel", "010-1234-5678");
		h.put("job", "탐정");
		h.put("address", "서울시");
		h.put("name", "너굴"); // 식별자의 중복을 불허하며, 식별자가 중복되는 경우 마지막에 등록한 값을 저장
		// h.put("zipcode", null); // 실행시 NullPointerException; 값에 null을 인정하지 않음
		// h.put(null, "마포구"); // 실행시 NullPointerException; 식별자에 null을 인정하지 않음
		System.out.println(h);
		
		// get() 메서드에 식별자를 인자로 입력하여 연결된 값을 반환받음
		String name = h.get("name");
		System.out.println("name = " + name);
		System.out.println();
		
		// h에 저장된 식별자 구하기; keys() 메서드를 통해 Enumeration 객체로 복사해야 함
		Enumeration<String> en = h.keys();
		while(en.hasMoreElements()) {
			String key = en.nextElement();
			System.out.println(key + " = " + h.get(key));
		}
	}		
}
외부 클래스명$내부 클래스명.class 형식으로 컴파일됨ch10-inner 생성하고 새 패키지 kr.s01.member 생성 후 새 클래스 MemberMain01 생성package kr.s01.member;
class Outer {
	// 멤버 변수
	int x = 100;
	// 인스턴스 내부 클래스
	class Inner {
		int y = 200;
	}
}
public class MemberMain01 {
	public static void main(String[] args) {
		Outer ot = new Outer();
		System.out.println(ot);
		System.out.println("x = " + ot.x);
		
		System.out.println();
		
		// 인스턴스 내부 클래스의 자료형은 .으로 외부 클래스명을 함께 명시해야 하며, 객체 생성은 외부 클래스의 객체에 .으로 접근 후 new와 생성자 사용
		Outer.Inner oi = ot.new Inner();
		System.out.println(oi);
		System.out.println("y = " + oi.y);	
	}
}
MemberMain02 생성package kr.s01.member;
class Outer2 {
	// 멤버 변수
	private int x = 100;
	// 인스턴스 내부 클래스
	class Inner2 {
		private int y = 200;
		public void make() {
			System.out.println("x = " + x); // x와 Inner2가 모두 Outer2의 멤버로 인식되기 때문에 Outer2의 private 변수를 Inner2에서 바로 접근 가능
			System.out.println("y = " + y);
		}
	}
}
public class MemberMain02 {
	public static void main(String[] args) {
		Outer2 ot = new Outer2();
		Outer2.Inner2 oi = ot.new Inner2();
		oi.make();
	}
}
MemberMain03 생성package kr.s01.member;
class Outer3 {
	// 멤버 변수
	int value = 10;
	// 인스턴스 내부 클래스
	class Inner3 {
		int value = 20;
		public void method1() {
			int value = 30;
			System.out.println("지역 변수 value : " + value);
			System.out.println("Inner3의 멤버 변수 value : " + this.value);
			System.out.println("Outer3의 멤버 변수 value : " + Outer3.this.value);
		}
	}
}
public class MemberMain03 {
	public static void main(String[] args) {
		Outer3.Inner3 oi = new Outer3().new Inner3(); // 외부 클래스의 객체를 호출할 일이 없다면 참조 변수를 따로 만들지 않아도 됨
		oi.method1();
	}
}