학원 19일차 - Java

·2021년 4월 24일
0

2021.04.22

형변환 - Object 클래스

  • Boxing
    • 값형의 데이터를 Object 변수에 담을 때 발생하는 현상
  • UnBoxing
    • Object 변수의 값형 데이터를 (올바르게) 사용하려면 원래 값형으로 형변환을 해야 한다.
public class Ex55_Cast {
	
	public static void main(String[] args) {
		
		AAA a = new AAA(); //자기 타입
		AAA b = new BBB(); //업캐스팅. 부모=자식
		AAA c = new CCC(); //업캐스팅. 할아버지=손자
		AAA d = new DDD(); //업캐스팅. 증조할아버지=증손자
		
		Object o1 = new Object();
		
		Object o2 = new AAA(); //업캐스팅
		Object o3 = new BBB();
		Object o4 = new CCC();
		Object o5 = new DDD();
		
		Object o6 = new Random();
		Object o7 = Calendar.getInstance();
		Object o8 = new BufferedReader(new InputStreamReader(System.in));
		Object o9 = new int[5];
		Object o10 = "문자열";
		
		//Object -> 만능 주머니★★★★★★★★★★★★★★★
		
		//배열 특징: 같은 자료형의 집합
        //Object로 배열을 만들었을때 Object의 모든 자식을 넣을 수 있다.
		Object[] list = new Object[10];
		
		list[0] = new AAA();
		list[1] = new BBB();
		list[2] = new Random();
		
        //AAA타입으로 배열을 만들면 AAA타입만 넣을 수 있다.
		AAA[] list2 = new AAA[3];
		
		list2[0] = new AAA();
		list2[1] = new AAA();
		
		//위의 내용 -> 참조형을 Object 변수에 넣었음.
		
        //int와 Integer의 목적은 같다. 
		int n = 123; //값형 int
		Integer n11 = new Integer(100); //참조형 int
		System.out.println(n + n11);
		
		//??? -> 값형을 넣었음.
		//Boxing(박싱)
		// - 값형의 데이터를 Object 변수에 담을 때 발생하는 현상
        //주소값이 필요하기 때문에 값형 int 대신 참조형 객체인 Integer이 만들어진다.
		Object o11 = 100; //new Integer(100) 실행 -> 주소값 -> o11 저장
		Object o12 = true; //new Boolean(true) 실행 -> 주소값 -> o12 저장
		
		System.out.println(o11); //100
		System.out.println(o11.toString());
		System.out.println(o12); //true
		
		//모든 산술 연산자는 피연산자로 객체를 가질 수 없다.
        //이유? -> 객체는 데이터의 집합 -> 그 중 누구를 연산의 대상으로 할지 알 수가 없기 때문
		//System.out.println(o11 + 100); //200
		System.out.println((int)o11 + 100); //예외 케이스 -> 값형과 참조형간에는 형변환이 발생할 수 없다!!!
		System.out.println((Integer)o11 + 100); //다운캐스팅 int-> Object -> int
		
        //Object에 담은 값형은 꺼냈을때 원래 타입으로 고치지 않으면 써먹을 수 없다.★★★★★
		
//		Time t1 = new Time();
//		t1.hour = 1;
//		t1.min = 10;
//		
//		Time t2 = new Time();
//		t2.hour = 2;
//		t2.min = 5;
//		
//		System.out.println(t1 + t2); //-> 어떤 변수를 연산해야할 지 알 수 없음.
		
		
		if ((boolean)o12) {
			System.out.println("참");
		} else {
			System.out.println("거짓");
		}
		
		
		//★★★★ 모든 값형의 데이터도 Object 변수에 넣을 수 있다.
		// -> Boxing 발생 //비용 발생
		
		//★★★★ Object 변수의 값형 데이터를 (올바르게) 사용하려면 원래 값형으로 형변환을 해야 한다.
		// -> UnBoxing 발생 //비용 발생
		
		int n1 = 10;
		Object n2 = 10; //객체 1개 생성 - Boxing
		
		System.out.println(n1 + 10);
		System.out.println((int)n2 + 10); //객체 1개 소멸 - UnBoxing
		
		
		//Object 사용 중 단점 -> 값을 집어넣는 건 편하지만 안에 뭐가 들어있는지 기억하고 사용하기 어렵다.
		//o5 -> 뭐가 들어있는지 알기 어렵다.-> 일의 흐름을 방해한다. 
		//System.out.println(o5); 
		//System.out.println((Random)o5); -> 잘못 캐스팅 할 위험이 있음
		
		//n1 -> 뭐가 들어있는지?
		System.out.println(n1);
		
	}//main
	
}

class Time {
	public String name;
	public int hour;
	public int min;
}

class AAA extends Object {
	
}

class BBB extends AAA {
	
}

class CCC extends BBB {
	
}

class DDD extends CCC {
	
}

  • Object o11 = 100;

형변환 사례 - 상속, 참조형 형변환, 배열, 제어문, 추상클래스(추상메소드) or 인터페이스(추상메소드)

​ [상황]

  1. 대리점 운영
  2. 전자 제품 > 프린터 판매
  3. LG300 x 5대, HP400 x 3대

​ [운영방침]

  1. 주기적으로 > 매장의 모든 제품이 정상적으로 동작하는지 체크 > 출력 기능

​ [상황 변경]

  1. 프린터 재고 증가 > LG300(100대), HP400(50대)
  2. 브랜드 증가 > Dell500, BenQ600, Epson700.. 10종 증가
  3. 각 브랜드 제품별 고유 기능도 점검(LG300.call(), HP400.selfTest())
가장 원시적인 방법
public class Ex56_Cast {
	
	public static void main(String[] args) {
        
        //가장 원시적인 방법
		LG300 lg1 = new LG300();
		LG300 lg2 = new LG300();
		LG300 lg3 = new LG300();
		LG300 lg4 = new LG300();
		LG300 lg5 = new LG300(); //100번 반복
		
		HP400 hp1 = new HP400();
		HP400 hp2 = new HP400();
		HP400 hp3 = new HP400(); //50번 반복
		
		
		//매일 1회 점검
		lg1.print();
		lg2.print();
		lg3.print();
		lg4.print();
		lg5.print(); //100번
		
		hp1.print();
		hp2.print();
		hp3.print(); //50번
        
    }
}


//LG300, HP400 -> 프린터
//1. 공통된 정보(데이터,변수), 기능(행동,메소드) -> 상속 -> 클래스 or 추상클래스 or 인터페이스(X) 
//2. 공통된 사용법(있으면 좋겠다.) -> 인터페이스 or 추상클래스 상속

//프린터로서 갖춰야할
// - 구현 멤버와
// - 추상 멤버를
//물려주기 위해서 만든 부모 클래스(추상 클래스)
abstract class Printer {
	
	//구현 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통 구현 기능
	public String model;
	public int price;
	public int ink;
	
	public void info() {
		System.out.printf("모델명: %s\n,잉크량: %dml\n,가격: %,d원\n"
							, this.model, this.price, this.ink);
	}
	
	
	//추상 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통적인 사용법
	// - 사용법은 동일해도.. 그 내부의 구현 내용은 각자가 알아서 구현한다.(****)
	public abstract void print();
	
}

class LG300 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. LG 맘대로.. LG 독자적인 기술 구현
		System.out.println("LG300으로 잉크젯을 사용해서 출력합니다.");
	}
	
	//LG300만이 가지는 유일한 기능
	public void call() {
		System.out.println("상담원과 연결합니다.");
	}
	
}

class HP400 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. HP 맘대로.. HP 독자적인 기술 구현
		System.out.println("HP400으로 레이저 출력을 합니다.");
	}
	
	//HP400만이 가지는 유일한 기능
	public void selfTest() {
		System.out.println("자가진단을 합니다.");
	}
	
}
향상된 방법 - 배열 사용
public class Ex56_Cast {
	
	public static void main(String[] args) {
        
        //향상된 방법 - 배열 사용
		
		LG300[] lgs = new LG300[5];
		
        //재고 확보
		for (int i=0; i<lgs.length; i++) {
			lgs[i] = new LG300();
		}
		
		HP400[] hps = new HP400[3];
		
		for (int i=0; i<hps.length; i++) {
			hps[i] = new HP400();
		}
		
		//재고 확보 배열 생성 + for -> 10번 반복(브랜드 종류만큼 반복)
		
		
		//매일 반복 점검 -> 브랜드 종류만큼 for 증가
		for (int i=0; i<lgs.length; i++) {
			lgs[i].print();
			lgs[i].call();
		}
		
		for (int i=0; i<hps.length; i++) {
			hps[i].print();
			hps[i].selfTest();
		}
    }
}

//프린터로서 갖춰야할 구현 멤버와 추상 멤버를 물려주기 위해서 만든 부모 클래스(추상 클래스)
abstract class Printer {
	
	//구현 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통 구현 기능
	public String model;
	public int price;
	public int ink;
	
	public void info() {
		System.out.printf("모델명: %s\n,잉크량: %dml\n,가격: %,d원\n"
							, this.model, this.price, this.ink);
	}
	
	
	//추상 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통적인 사용법
	// - 사용법은 동일해도.. 그 내부의 구현 내용은 각자가 알아서 구현한다.(****)
	public abstract void print();
	
}

class LG300 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. LG 맘대로.. LG 독자적인 기술 구현
		System.out.println("LG300으로 잉크젯을 사용해서 출력합니다.");
	}
	
	//LG300만이 가지는 유일한 기능
	public void call() {
		System.out.println("상담원과 연결합니다.");
	}
	
}

class HP400 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. HP 맘대로.. HP 독자적인 기술 구현
		System.out.println("HP400으로 레이저 출력을 합니다.");
	}
	
	//HP400만이 가지는 유일한 기능
	public void selfTest() {
		System.out.println("자가진단을 합니다.");
	}
	
}


class Dell500 extends Printer {
	@Override
	public void print() {
		// TODO Auto-generated method stub
		
	}
}
더욱 향상된 방법 - 배열 사용 + 형변환(업캐스팅, 다운캐스팅), 실용적인 방법(실제 업무 많이 사용)
  • instanceof 연산자
    • 2항 연산자
    • '객체 instanceof 타입' 으로 구성되어있음
    • 앞의 객체를 뒤의 자료형으로 형변환이 가능합니까?라는 뜻
public class Ex56_Cast {
	
	public static void main(String[] args) {
   
		//Printer <-> LG300, HP400  : 상속관계
		
		//Case A.
		Printer p1 = new LG300(); //부모클래스 = 자식클래스 //업캐스팅
		Printer p2 = new HP400(); //부모클래스 = 자식클래스 //업캐스팅
		
		//Case B.
		Printer[] ps = new Printer[2];
		ps[0] = new LG300();
		ps[1] = new HP400();
		
		
		//**** 핵심 -> LG 5대 + HP 3대 -> 하나의 배열에 저장
		Printer[] list = new Printer[8]; 
		
        //순서대로 배열에 저장
		for (int i=0; i<list.length; i++) {
			if (i < 5) {
				list[i] = new LG300();
			} else {
				list[i] = new HP400();
			}
		}
		
		
		//매일 점검
		for (int i=0; i<list.length; i++) {
			
			//공통 기능 -> 추상 메소드 -> 겉으로는 동일해보여도.. 실제로는 하는일 각각 다르다.
			list[i].print();
			
			//공통 기능 -> 구현 상속 메소드 -> 겉으로도 동일하고.. 실제로 하는일도 동일하다.
			//list[i].info();
			
			
			//list[i]의 자료형 -> Printer
			//다운 캐스팅
			
			//if (i < 5) { //-> 배열순서대로 담겨있어야 사용할 수 있다.
			//	LG300 lg = (LG300)list[i]; //다운 캐스팅
			//	lg.call();
			//} else {
			//	HP400 hp = (HP400)list[i];
			//	hp.selfTest();
			//}
			
			
			//instanceof 연산자
			// - 2항 연산자
			// - 객체 instanceof 타입
            // - 결과 Boolean형으로 나옴 true, false
			// - 앞의 객체를 뒤의 자료형으로 형변환이 가능합니까?라는 뜻
			//System.out.println(list[i] instanceof LG300);
			
			if (list[i] instanceof LG300) {
				LG300 lg = (LG300)list[i];
				lg.call();
			} else if (list[i] instanceof HP400) {
				HP400 hp = (HP400)list[i];
				hp.selfTest();
			}
		}
    }
}


abstract class Printer {
	
	//구현 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통 구현 기능
	public String model;
	public int price;
	public int ink;
	
	public void info() {
		System.out.printf("모델명: %s\n,잉크량: %dml\n,가격: %,d원\n"
							, this.model, this.price, this.ink);
	}
	
	
	//추상 멤버
	// - 회사나 모델에 상관없이 모든 프린터가 가져야할 공통적인 사용법
	// - 사용법은 동일해도.. 그 내부의 구현 내용은 각자가 알아서 구현한다.(****)
	public abstract void print();
	
}

class LG300 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. LG 맘대로.. LG 독자적인 기술 구현
		System.out.println("LG300으로 잉크젯을 사용해서 출력합니다.");
	}
	
	//LG300만이 가지는 유일한 기능
	public void call() {
		System.out.println("상담원과 연결합니다.");
	}
	
}

class HP400 extends Printer {
	
	//모든 프린터의 사용법을 통일시키기 위해서 만든 멤버
	@Override
	public void print() {
		//내용만의 내맘대로.. HP 맘대로.. HP 독자적인 기술 구현
		System.out.println("HP400으로 레이저 출력을 합니다.");
	}
	
	//HP400만이 가지는 유일한 기능
	public void selfTest() {
		System.out.println("자가진단을 합니다.");
	}
	
}

class Dell500 extends Printer {
	@Override
	public void print() {
		
	}
}

자료형

  1. 값형(원시형)

    a. 정수(byte, short, int, long)

    b. 실수(float, double)

    c. 문자(char)

    d. 논리(boolean)

  2. 참조형

  • 모두 클래스

    a. String

    b. 배열

    c. 클래스

  1. 일반 클래스
  2. 추상 클래스
  3. 인터페이스
  4. enum
  5. 제네릭 클래스

제네릭, Generic

  • 클래스의 일종
  • Object 처럼 모든 자료형을 제어할 수 있다.
  • 전용 클래스처럼 형변환없이 데이터를 바로 사용이 가능하다.(Object는 다운캐스팅이 필요하다.)
public class Ex57_Generic {
	
	public static void main(String[] args) {
        
        //int
        WrapperInt n1 = new WrapperInt(100);
		System.out.println(n1);
		System.out.println(n1.getData() * 2);
		
		
		WrapperObject n2 = new WrapperObject(200);
		System.out.println(n2);
		System.out.println((int)n2.getData() * 2);
		
		
		Wrapper<Integer> n3 = new Wrapper<Integer>(300); //전용(WrapperInt) + 범용(WrapperObject)
		System.out.println(n3);
		System.out.println(n3.getData() * 2);
		
		//String
		WrapperString s1 = new WrapperString("홍길동");
		System.out.println(s1);
		System.out.println(s1.getData().length());
		
		
		WrapperObject s2 = new WrapperObject("안녕하세요");
		System.out.println(s2);
		System.out.println(((String)s2.getData()).length()); //★괄호로 묶어서 형변환을 먼저 하고 .length를 찍어야한다. 
		
		
		Wrapper<String> s3 = new Wrapper<String>("지금 자바를 공부하고있습니다.");
		System.out.println(s3);
		System.out.println(s3.getData().length());
	
		
		//boolean
		WrapperBoolean b1 = new WrapperBoolean(true);
		System.out.println(b1);
		System.out.println(b1.getData() ? "참" : "거짓");
		
		
		WrapperObject b2 = new WrapperObject(false);
		System.out.println(b2);
		System.out.println((boolean)b2.getData() ? "참" : "거짓");
		
		
		Wrapper<Boolean> b3 = new Wrapper<Boolean>(true);
		System.out.println(b3);
		System.out.println(b3.getData() ? "참" : "거짓");

    }
}


//요구사항] 
//1. int 값 1개를 중심으로 여러가지 작업을 하는 클래스를 선언하시오.
//2. String 값 1개를 중심으로 여러가지 작업을 하는 클래스를 선언하시오.
//3. Booean 값 1개를 중심으로 여러가지 작업을 하는 클래스를 선언하시오.
//4. byte
//5. short
//6. long
//7. float
//8. double
//9. char
//10. Random
//11. Calendar
//12. Student
//..
//무한대.


class WrapperInt {
	
	private int data; //중심 데이터
	
	public WrapperInt(int data) { //생성자
		this.setData(data);
	}

	public int getData() {
		return data;
	}

	public void setData(int data) {
		this.data = data;
	}
	
	public String toString() { //오버라이드
		
		//int -> String
		//return (String)this.data;
		
		//return String.valueOf(this.data); //정석(표준방법)
		return this.data + ""; //편법
        
	}
	
}


class WrapperString {
	
	private String data;
	
	public WrapperString(String data) {
		this.setData(data);
	}

	public String getData() {
		return data;
	}

	public void setData(String data) {
		this.data = data;
	}
	
	public String toString() {
		return this.data;
	}
	
}




class WrapperBoolean {
	
	private boolean data;
	
	public WrapperBoolean(boolean data) {
		this.setData(data);
	}

	public boolean getData() {
		return data;
	}

	public void setData(boolean data) {
		this.data = data;
	}
	
	public String toString() {
		return this.data + "";
	}
	
}


//방법1 - 단점 : 값형을 넣었을때 boxing, UnBoxing이라는 추가비용 발생, 안에 뭐가 들었는지 알기 어려움.
class WrapperObject {
	
	private Object data;
	
	public WrapperObject(Object data) {
		this.setData(data);
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
	
	public String toString() {
		return this.data + "";
	}
	
}


//방법2 - 제네릭
class Wrapper<T> {
	
	private T data;
	
	public Wrapper(T data) {
		this.data = data;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}
	
	@Override
	public String toString() {
	
		return this.data + "";
	}
	
}
  • 제네릭 선언하기
    • class Item { } => T : 타입 변수 -> 데이터를 저장하는 용도가 아니라, 자료형 자체를 저장하는 용도
  • 형변환 없이 사용이 가능하다.
public class Ex58_Generic {
	
	public static void main(String[] args) {
		
		//Ex58_Generic.java
		
		Item<String> item1 = new Item<String>();
		item1.c = "홍길동";
		System.out.println(item1.c.length());
		
		//Item<int> item4;
		Item<Integer> item2 = new Item<Integer>();
		item2.c = 10;
		System.out.println(item2.c * 2);
		
		Item<Boolean> item3 = new Item<Boolean>();
		item3.c = true;
		System.out.println(item3.c ? "참" : "거짓");
		
		
		
		Mouse<String> m1 = new Mouse<String>();
		m1.a = "문자열";
		m1.b = "홍길동";
		m1.c = "String";
		
		
		
		Keyboard<Boolean> k1 = new Keyboard<Boolean>();
		k1.a = true;
		k1.test(true);
		System.out.println(k1.get());
		
		
		Keyboard<Boolean> k2 = new Keyboard(); //사용하지 말것
		k2.a = false;
		
		
		Computer<String,Integer> c = new Computer<String,Integer>();
		
		c.set("홍길동", 20);
		
		System.out.println(c.getA());
		System.out.println(c.getB());
		
		
	}//main

}


//제네릭 클래스 선언하기
// - T: 타입 변수 -> 데이터를 저장하는 용도가 아니라, 자료형 자체를 저장하는 용도
//		ex) T = int
//		ex) T = String
//		ex) T = Random
class Item<T> {
	
	//멤버
	public int a;
	public String b;
	public T c; //Object 느낌 -> 뭐든지 담을 수 있는 자료형
	
}


class Mouse<T> {
	
	public T a;
	public T b;
	public T c;
	
}

class Keyboard<T> {
	
	public T a;
	
	public void test(T n) {
		//T m;//지역 변수를 사용할 수 없다. -> 겉으로 드러난 부분에만 사용을 권장
	}
	
	public T get() {
		return a;
	}
	
}


class Computer<T,U> {
	
	public T a;
	public U b;
	
	public void set(T a, U b) {
		this.a = a;
		this.b = b;
	}
	
	public T getA() {
		return this.a;
	}
	
	public U getB() {
		return this.b;
	}
	
}

Wrapper Class, Util Class...

  • int -> Integer
  • double -> Double
  • boolean -> Boolean
public class Ex59 {
	
	public static void main(String[] args) {
        
		//1.
		System.out.println(Integer.parseInt("100") + 100);
		
		//2.
		System.out.println(Integer.MAX_VALUE); //final static 상수
		System.out.println(Integer.MIN_VALUE);
		
		//3.
		System.out.println(Integer.compare(10, 5)); //1  -> 앞의 값이 크다
		System.out.println(Integer.compare(5, 10)); //-1 -> 뒤의 값이 크다
		System.out.println(Integer.compare(10, 10));//0  -> 같다
		
		//4. 둘 중에 더 큰 걸 반환
		System.out.println(Integer.max(10, 5));
		System.out.println(Integer.min(10, 5));
		System.out.println(Integer.max(5, 10));
		System.out.println(Integer.min(5, 10));
		
		//5.
		System.out.println(10 + "");
		System.out.println(String.valueOf(10));
		System.out.println(Integer.toString(10));
		
		//6.
		System.out.println(Integer.toBinaryString(10)); //1010 -> 2진수
		System.out.println(Integer.toHexString(255)); //ff -> 16진수
		System.out.println(Integer.toOctalString(10)); //12 -> 8진수
		
		
		String s1 = "A";
		String s2 = "B";
		
		//System.out.println(s1 > s2); //주소값 비교
		
		System.out.println(s1.charAt(0) > s2.charAt(0)); //값 비교 -> 문자코드값 비교
		
		
        //정렬(Sort)
		// - 숫자: 크기 정렬
		// - 문자: 문자코드 정렬(숫자 정렬)
        
        s1 = "홍길동";
		s2 = "아무개";
        
		//s1 = "ABC";
		//s2 = "abc";
	
		//System.out.println(s1 > s2);
		
		System.out.println(compareString(s1, s2)); //앞이 크다(1), 뒤가 크다(-1), 같다(0)
		
        s1 = "홍길동";
		s2 = "홍길동입니다";
     
		System.out.println(s1.compareTo(s2)); //앞이 크다(양수), 뒤가 크다(음수), 같다(0) => (숫자 에 의미가 없음 음수, 양수, 0 인지만 파악.)

       	s1 = "ABC";
		s2 = "abc";
        
		System.out.println(s1.compareToIgnoreCase(s2)); //영어일때, 대소문자 가리지 않고 비교.
		
		
	}//main
	
	private static int compareString(String s1, String s2) {
		
        //compareToIgnoreCase 안쓰고 대소문자 구분 없이 비교하는 방법
		//s1 = s1.toUpperCase();
		//s2 = s2.toUpperCase();
		
		//s1 = "홍길동";
		//s2 = "남궁성진";
		
		int min = 0;
		
		if (s1.length() < s2.length()) { //글자 길이 비교 -> for문이 몇번 돌아야하는지 결정
			min = s1.length();
		} else {
			min = s2.length();
		}
		
		min = Integer.min(s1.length(), s2.length()); //둘 중에 더 큰 걸 반환
		
        //문자 코드 값 비교
		for (int i=0; i<min; i++) {
			if (s1.charAt(i) > s2.charAt(i)) { //첫글자부터 비교
				return 1;
			} else if (s1.charAt(i) < s2.charAt(i)) {
				return -1;
			}
		}
		
        //똑같은 글자 뒤에 더 적혀있으면 실행되는 코드
		if (s1.length() > s2.length()) {
			return 1;
		} else if (s1.length() < s2.length()) {
			return -1;
		}
		
		return 0; //글자가 똑같은 경우 0을 반환
		
	}

}

Scanner

  • 자료형별로 입력 메소드가 각각 존재한다. > parseXXX 필요없음
Scanner scan = new Scanner(System.in); //System.in.read() 메소드 사용 -> Wrapper Class

System.out.print("입력: ");

String line = scan.nextLine(); //reader.readLine() 동일

System.out.println(line);

int num = scan.nextInt(); //입력받은 데이터를 바로 숫자로 받을 수 있다 -> 변환할필요 없음
System.out.println(num + 100);

예외 , Exception

  • 컴파일X, 런타임O
  • 개발자 예측O, X -> 예측을 하더라도 발생할 수 있다.
  • 나중에 일어날 수 있는 여러가지 예외 상황을 미리 예측해서 그에 따른 대비를 하는 작업 -> 예외 처리
  • 예외 처리, Exception Handling
    1. 전통적인 방법
      • 제어문(조건문) 사용
    2. 예외처리 구문
      • try catch문
public class Ex60_Exception {
    public static void main(String[] args) { 
        
        Scanner scan = new Scanner(System.in);
		
		System.out.print("숫자 입력: ");
		
		int num = scan.nextInt();
	
		//예외 처리
		
		//예외 조건
		if (num != 0) {
			//업무 코드(비즈니즈 코드)
			System.out.printf("100 / %d = %d\n", num, 100 / num);
		} else {
			//예외 처리 코드
			System.out.println("0을 입력하면 안됩니다.");
		}
		
		//자바는 if-else로 예외를 처리하기 보단 try-catch로 처리하는 것을 더 권장한다.
        
		//(num != 0)같은 예외 조건이 없다.
		// -> 일단 에러 발생시키고 -> catch절로 이동 -> 마무리를 한다.
		try {			
			//비지니스 코드 
			System.out.printf("100 / %d = %d\n", num, 100 / num); // new Exception() 발생
			
			System.out.println("다음 코드");
			
		} catch(Exception e) {	//Exception e - 에러 발생과 관련된 일련의 정보를 담고 있는 객체		
			
            //예외처리코드
			System.out.println("0을 입력하면 안됩니다.");
			System.out.println(e.getMessage()); // - / by zero, 에러메세지
			System.out.println(e.getStackTrace()); //어디에서 오류가 났는지
			System.out.println(e.toString()); //java.lang.ArithmeticException: / by zero 프로그램 종료 , 상태를 문자열로 반환
		}
		
		System.out.println("프로그램 종료");
    }
}

a. try -catch를 3번이나 쓰였기 때문에 가독성이 떨어진다. 업무코드보다 예외처리코드가 불필요하게 많음.

public class Ex60_Exception {
    public static void main(String[] args) {
        //업무 1.
		try {
			
			int[] nums = { 100, 200, 300 };
			nums[5] = 500;
			
		} catch (Exception e) {
			System.out.println("방번호가 올바르지 않습니다.");
		}
		
		
		//업무 2.
		try {
			
			Random rnd = null;
			System.out.println(rnd.nextInt());
			
		} catch(Exception e) {
			System.out.println("Random 객체를 생성하지 않았습니다.");
		}
		
		
		//업무 3.
		try {
			
			int n = 0; //사용자 입력
			System.out.println(100 / n);
			
		} catch (Exception e) {
			System.out.println("0으로 나누려고 했습니다.");
		}
		
		
		System.out.println("프로그램 종료");
    }
}

b. 여러 종류의 에러가 날 코드를 하나의 try-catch로 묶는다. 한번에 감시 가능.

에러가 나는 코드 뒤의 코드는 실행하지 않는다.

public class Ex60_Exception {
    public static void main(String[] args) {

        try {

            //업무 1.
            int[] nums = { 100, 200, 300 };
            nums[5] = 500;
            System.out.println("업무1");

            //업무 2.
            Random rnd = null;
            System.out.println(rnd.nextInt());
            System.out.println("업무2");

            //업무 3.
            int n = 0; //사용자 입력
            System.out.println(100 / n);
            System.out.println("업무3");

        } catch (Exception e) {

            System.out.println("예외를 처리했습니다."); // 어디서 예외가 생겼는지 알기 어렵다.(에러멘트 구분 불가.)
            //개발자
            //System.out.println(e.getMessage()); //개발자의 입장에서만 에러 구분 가능.

        }

        System.out.println("프로그램 종료");
    }
}

c. 다중 catch절 - catch 여러번 사용해서 매개변수에 따라 에러 구분

public class Ex60_Exception {
    public static void main(String[] args) {
        try {

            //업무 1.
            int[] nums = { 100, 200, 300 };
            nums[0] = 500; //new ArrayIndexOutOfBoundsException() 객체 생성 == 야구공(객체)
            System.out.println("업무1");

            //업무 2.
            Random rnd = new Random();// null;
            System.out.println(rnd.nextInt()); //new NullPointerException() 객체 생성 == 야구공(객체)
            System.out.println("업무2");

            //업무 3.
            int n = 10; //사용자 입력
            System.out.println(100 / n); //new ArithmeticException() 객체 생성 == 야구공(객체)
            System.out.println("업무3");

            System.out.printf("%d", "홍길동");

        } catch (ArrayIndexOutOfBoundsException e) { //객체를 매개변수가 받음.

            System.out.println("배열 오류");

        } catch (NullPointerException e) {

            System.out.println("널참조 오류");

        } catch (ArithmeticException e) {

            System.out.println("산술 연산 오류");

        } catch (Exception e) { //Exception - 모든 XXXException 클래스의 부모 클래스★

            System.out.println("오류");

        }

        System.out.println("프로그램 종료");
    }
}

d. 예외던지기 - 문법적인 오류가 아닌 상황에서 예외를 강제로 발생시킬 때 사용하는 도구

public class Ex60_Exception {
    public static void main(String[] args) {
        //예외 던지기
		
		//업무] 숫자입력 > 3의 배수 O > 진행
		//				        X > 예외 처리
		
		Scanner scan = new Scanner(System.in);
		
		System.out.print("숫자: ");
		
		int num = scan.nextInt();
		
		
		if (num % 3 == 0) {
			System.out.println("업무 진행..");
		} else {
			System.out.println("예외 처리..");
		}
		
		
		//try {
			
        	//3의 배수가 아닐때만 예외 발생
			if (num % 3 != 0) {
				Exception e = new Exception(); //객체 생성(= 야구공 생성)
				throw e; //예외 던지기 - 문법적인 오류가 아닌 상황에서 예외를 강제로 발생시킬 때 사용하는 도구
				
				//throw new Exception(); -> 만들자마자 던지는 방법. 에러가 났으면 하는 부분에 쓰임.
			}
//			
//			System.out.println("업무 진행..");
//		} catch (Exception e) {
//			System.out.println("예외 처리..");
//		}
    }
}

e. 예외 미루기

public class Ex60_Exception {
	
	//main메소드는 예외 미루기를 하면 안된다 -> 더 이상 책임져줄 메소드가 없기 때문에;;
	// -> 최후의 보루
	public static void main(String[] args) throws IOException { //본사 -> 결국 에러 발생;;;
	
		try {
			m7();
		} catch (Exception e) {
			System.out.println(e);
		}
		
		m8();
		
	}//main
	
	private static void m8() throws IOException {
		
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		
		//자바는 모든 외부 입출력은 예외 미루기 선언이 되어있음
		// -> 외부 입출력은 개발자의 의도와 상관없이 에러 발생할 가능성이 있기 때문에
		// -> 반드시 try catch를 준비해라!!
		String line = reader.readLine();
		
        //try{
        //    String line = reader.readLine();
        //} catch (){
        //    System.out.println("입력실패");
        //}
		
	}
	
//	public String readerLine() throws Exception {
//		
//	}

	private static void m7() throws Exception { //예외 미루기 -> 호출한 곳으로 넘기기
		
		//try의 영역은 최소화하는 것을 추천한다. -> try는 구문을 계속 감시하기 때문에 비용이 든다.(프로그램이 무거워진다.)
		
        //try{ -> 전체를 try로 묶으면 안정성이 높아진다. 예측 못한 부분의 예외도 처리할 수 있기 때문에. 
        
		//예외 미루기
		Scanner scan = new Scanner(System.in);
		
		System.out.print("숫자: ");
		
		int num = scan.nextInt();
		
		//try {
			System.out.println(100 / num);
		//} catch (Exception e) {
		//	System.out.println("예외 처리");
		//}
		
	}

-> 예외 미루기 : 본사에 처리를 떠넘기는 것.


컬렉션 - ArrayList

  • Java Collection Framework (JCF)
  • 배열 -> 향상된 배열
  • 배열을 기반으로 특정한 사용 목적이나, 특정한 사용 방식을 구현해 놓은 클래스
  • 자료 구조 -> 이름 붙여 놓은 것들 -> 컬렉션
  • 10여종 + 직접 구현

ArrayList 클래스

  • 가장 많이 사용하는 컬렉션 클래스
  • 가장 보편적인 구조를 가진다.
  • 순수 배열과 구조가 거의 비슷하다.
  • 첨자(index)를 사용해서 요소(Element)에 접근/제어
  • Object형
순수배열과 컬렉션ArrayList 비교
  • .add : 순서대로 알아서 넣는 메소드(비어있는 방에 순서대로 집어넣는다.)
import java.util.ArrayList;

public class Ex61_ArrayList {
	
	public static void main(String[] args) {
        //순수 배열
		
		//배열 선언
		//- 타입 명시(int)
		//- 길이 명시(3)
		int[] num1 = new int[3];
		
		//초기화 + 요소접근 -> 첨자(index) 사용
		num1[0] = 100;
		num1[1] = 200;
		num1[2] = 300;
		
		System.out.println(num1[0]);
		
		//탐색
		for (int i=0; i<num1.length; i++) {
			System.out.println(num1[i]);
		}
		
		for (int n : num1) {
			System.out.println(n);
		}
		System.out.println();
		System.out.println();
		
		
		//컬렉션
		//ArrayList
		//- 타입 없음(int) -> Object 배열
		//- 길이 없음(3) -> 가변(늘리거나 줄일 수 있다.) ★★★★★★★★★★
		ArrayList num2 = new ArrayList();
		
		//초기화
		//num2[0] = 100; //[0] : Indexer -> 자바는 순수 배열만 인덱서를 지원한다.
		
		//add -> 순서대로 알아서 넣는 메소드(비어있는 방에 순서대로 집어넣는다.)
		//Append
		num2.add(100); //0번방
		num2.add(200); //1번방
		num2.add(300); //2번방
		
		num2.add(400); 
		num2.add(500);
		
		System.out.println(num2.size()); //길이 확인할때 : size()
		
		//System.out.println(num2[0]);
		System.out.println(num2.get(0)); //값을 꺼낼때 : get()
		
        //탐색
		for (int i=0; i<num2.size(); i++) {
			System.out.println(num2.get(i));
		}
		
        //Object배열이기 때문에 형변환 후 사용할 수 있다.
		System.out.println((int)num2.get(0) * 2); //(다운캐스팅)
		
		
		for (Object n : num2) {
			System.out.println((int)n);
		}
    }
}

제네릭버전 - ArrayList

import java.util.ArrayList;

public class Ex61_ArrayList {
	
	public static void main(String[] args) {
        
        //일반 버전(Object 버전)
		ArrayList list1 = new ArrayList();
		
		list1.add(100);
		list1.add(200);
		list1.add(300);
		
		System.out.println((int)list1.get(0) + 100);
		
		System.out.println(list1.size());
		 
		for (int i=0; i<list1.size(); i++) {
			System.out.println(list1.get(i));
		}
		
		//제네릭 버전
		ArrayList<Integer> list2 = new ArrayList<Integer>(); //int 배열
		
		list2.add(100);
		list2.add(200);
		list2.add(300);
		
        //제네릭 버전은 (다운 캐스팅) 추가 작업없이 사용할 수 있다.
		System.out.println(list2.get(0) + 100);
		
		System.out.println(list2.size());
		
        //탐색
		for (int i=0; i<list2.size(); i++) {
			System.out.println(list2.get(i));
		}
		
		for (int n : list2) {
			System.out.println(n);
		}
    }
}
사용법 정리
import java.util.ArrayList;

public class Ex61_ArrayList {
	
	public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>(); //String 배열
		
		//1. 요소 추가하기
		// - boolean add(T value)
		// - 배열의 맨 마지막에 추가한다.(Append)
		list.add("빨강");
		list.add("노랑");
		list.add("파랑");
		list.add("연두");
		list.add("주황");
		
		
		//2. 요소의 갯수
		// - int size()
		System.out.println(list.size());
		
		
		//3. 요소의 접근 - 방번호를 입력하면 방의 값을 리턴 
		// - T get(int index)
		System.out.println(list.get(0));
		System.out.println(list.get(1));
		System.out.println(list.get(2));
		
		//System.out.println(list.get(5)); -> 없는 방번호 > 에러
		System.out.println(list.get(list.size()-1)); //마지막 방번호 : 최대길이 - 1
		
		
		
		//4. 요소의 수정
		// - list[0] = 100
		// - T set(int index, T value)
		System.out.println();
		System.out.println(list.get(2)); 
		String oldValue = list.set(2, "Blue"); // 수정되기 전 값을 반환값으로 알려주고 수정됨
		list.set(2, "Blue"); // 방번호, 수정할 값
		System.out.println(oldValue);
		System.out.println(list.get(2));
		
		
		//5. 요소의 삭제
		// - 순수 배열의 요소는 삭제 불가능
		// - 컬렉션은 요소의 삭제 가능
		// - T remove(int index) //- 방번호를 입력하면 지운 값을 돌려주고 지워줌. -> 더 많이 사용
		// - boolean remove(T value) -> 지우고 싶은 데이터를 입력하면 그 방을 찾아서 지워줌.
		
		System.out.println();
		System.out.println(list.size());
		
		for (String color : list) {
			System.out.println(color);
		}
		
		System.out.println("3번방: " + list.get(3)); //연두
		list.remove(2); // -> 중간에 값이 삭제되면 오른쪽 값들이 왼쪽으로 한칸씩 이동한다.
		System.out.println("3번방: " + list.get(3)); //주황
		
		System.out.println();
		System.out.println(list.size());
		
		for (String color : list) {
			System.out.println(color);
		}
		
		
		
		//6. 요소 추가
		// - 삽입(Insert)
		// - 중간에 끼워 넣기 -> 나멎; 
		// - void add(int index, T value) -> 오버로딩
		System.out.println();
		
		System.out.println("2번방: " + list.get(2)); //연두
		list.add(1, "오렌지"); //-> 한칸씩 밀려남
		System.out.println("2번방: " + list.get(2)); //노랑
		
		for (String color : list) {
			System.out.println(color);
		} //빨강 오렌지 노랑 연두 주황
		
		//질문 : 2를 입력하면 방번호로 인식? 데이터로 인식?
		ArrayList<Integer> num = new ArrayList<Integer>();
		
		num.add(0);
		num.add(2);
		num.add(4);
		num.add(6);
		
		//num.remove(2);//2 : 방번호?(O), 데이터?
		//num.remove(6);
		
		
		for (int n : num) {
			System.out.println(n);
		}
        
        
        //7. 검색
		// - 요소값 검색
		// - boolean contains(T value)
		// - int indexOf(T value)
		// - int lastIndexOf(T value)
		
		list.add("노랑");
		
		System.out.println(list.contains("노랑")); //있다? 없다?
		System.out.println(list.indexOf("노랑")); //몇번째? 방향(->)
		System.out.println(list.lastIndexOf("노랑")); //몇번째? 방향(<-)
		System.out.println();
		
		
		//8. 초기화
		// - 모든 방을 삭제
		list.clear(); //원래 배열을 초기화
		//list = new ArrayList<String>(); //새로운 배열로 덮어쓰기
		
		System.out.println(list.size());
		
		
		//9. 빈배열 확인
		System.out.println(list.size() == 0); //비어있니?
		System.out.println(list.isEmpty()); 
		
		
		//java.util.List 인터페이스 (조상)
		//java.util.ArrayList 클래스 (자식)
		
		ArrayList<String> a1 = new ArrayList<String>();
		
		//List<String> a2 = new List<String>(); //인터페이스는 객체를 만들 수 없다. (추상메소드가 있기때문)
		
		//★★★★ 결론: 인터페이스를 상속받은 클래스의 객체는 인터페이스 변수에 담아서 사용하는 경우가 많다.
		List<String> a2 = new ArrayList<String>(); //부모인터페이스 = 자식객체 //업캐스팅
		
    }
}
profile
모르면 괴롭고 알면 즐겁다.

0개의 댓글

관련 채용 정보