컬렉션 ( collection ) 을 사용한 객체 리스트

package collection;

import java.util.ArrayList;

class DTO01{
	private String name, id;
	
	// setter/getter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
}

public class Ex01 {
	public static void main(String[] args) {
		// DTO01 자료형 타입으로 자료를 받겠다
		ArrayList<DTO01> arr = new ArrayList<>();
		DTO01 d01 = new DTO01();
		d01.setName("홍길동");
		d01.setId("aaa");
		// DTO01 자료형 타입으로 생성된 d01 변수를
		// arr 에 0 번째 인덱스로 추가
		arr.add(d01);
		DTO01 dd = arr.get(0);
		System.out.println(dd.getId()); // aaa
		System.out.println(dd.getName()); // 홍길동
		
		
		DTO01 d02 = new DTO01();
		d02.setName("김개똥");
		d02.setId("bbb");
		arr.add(d02);
		System.out.println(arr.get(1).getId()); // bbb
		System.out.println(arr.get(1).getName()); // 김개똥
		
		// for 문을 사용하여 arr 에 저장된 DTO01 자료형의 값들 모두 출력
		for (int i=0; i<arr.size(); i++) {
			DTO01 ddd = arr.get(i);
			System.out.println("id : " + ddd.getId());
			System.out.println("이름 : " + ddd.getName());
			// id : aaa
			// 이름 : 홍길동
			// id : bbb
			// 이름 : 김개똥
			
		// for each 문을 사용하여 arr 에 저장된 DTO01 자료형의 값들 모두 출력
		for(DTO01 a : arr) {
			System.out.println("id : " + a.getId());
			System.out.println("이름 : " + a.getName());
			// id : aaa
			// 이름 : 홍길동
			// id : bbb
			// 이름 : 김개똥
			}
		}
	}
}

ArrayList 자료형에 DTO 자료형을 받게끔 객체를 생성하여 DTO 자료형의 값들을 저장 후 출력

보통 위와 같은 형식은 DataBase 에서 자료를 받아서 저장하고 출력할때 사용된다

 

package collection;

import java.util.ArrayList;
import java.util.Scanner;

class Dto02{
	private String name, id;
	
	// getter/setter
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	
}

public class Ex02 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String id, name;
		ArrayList<Dto02> arr = new ArrayList<>();
		while(true) {
			System.out.println("1.저장");
			System.out.println("2.모든 내용 확인");
			int num = sc.nextInt();
			switch(num) {
			case 1: 
				Dto02 d = new Dto02();
				System.out.print("아이디 입력 >> ");
				id = sc.next();
				d.setId(id);
				System.out.print("이름 입력 >> ");
				d.setName(sc.next());
				arr.add(d);
				System.out.println("저장되었습니다!!!");
				break;
			case 2: 
				for(Dto02 a : arr) {
					System.out.println("아이디 : " + a.getId());
					System.out.println("이름 : " + a.getName());
				}
				break;
			}
		}
	}
}

이름과 아이디를 입력받아 Dto02 클래스에 저장하고 저장된 내용을 arr 이라는 ArrayList 타입에 저장한뒤 출력까지 가능한 프로그램

728x90

 

 

 

 

 

쓰레드 ( Thread )

쓰레드 ( Thread )

( 쓰레드를 사용한다고 해서 동시에 2 가지 이상의 프로세스를 처리할 수 있는 것은 아니다 )

( 매우 빠른 속도로 연산하기 때문에 동시에 처리되는 것으로 보이는 것이다 )

 

package thread;

class A01 extends Thread{
	// 쓰레드를 상속
	public void run() {
		for(int i=0; i<100; i++)
			System.out.println("i : " + i);
	}
}

class B01 extends Thread{
	// 쓰레드를 상속
	public void run() {
		for(int k=0; k<100; k++)
			System.out.println("k : " + k);
	}
}

public class Ex01 {
	public static void main(String[] args) {
		A01 a = new A01();
		B01 b = new B01();
		
		// 일반적인 메소드 사용 방식
		// 순차적으로 모드가 진행됨
		// a.run();
		// b.run();
		
		// 쓰레드를 사용하여 메소드사용하여
		// 쓰레드를 적용하려면 start() 메소드를 사용하여 호출
		a.start();
		b.start();
	}
}

상속받아 쓰레드를 사용하는 방법

 

package thread;

import java.util.Scanner;

class A03 extends Thread{
	public void run() {
		for( ; ; ) {
			System.out.println("문자가 날라왔습니다!!!!");
			try {
				sleep(2000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

public class Ex03 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		String str;
		A03 a = new A03();
		// setDaemon = 현재 쓰레드를 종료시켜준다는 의미
		// 이 쓰레드의 종료 시점은 메소드가 실행된 곳이 종료되는 시점
		// 즉, main 이 종료되는 시점에 a 쓰레드도 실행이 종료된다
		a.setDaemon(true);
		// 쓰레드 실행
		a.start();
		
		while(true) {
			System.out.print("문자열 입력 : ");
			str = sc.next();
			System.out.println("입력한 값 : " + str);
			if(str.equals("end")) {
				System.out.println("종료합니다");
				break;
			}
		}
		System.out.println("main이 종료됩니다");
	}
}

입력 받음을 유지하면서 일정 문구를 출력하는 코드

.setDaemon() - 이 메소드를 사용하여 쓰레드가 실행된 곳이 종료될때 쓰레드도 같이 종료되게끔 설정한다

 

package thread;

class Test04 extends Thread{
	A04 a;
	public Test04(A04 a, int num) {
		this.a = a;
		System.out.println(num + " -> a : " + a);
	}
	public void run() {
		a.test();
	}
}

class A04{
	int sum = 1;
	public synchronized void test() {
	// synchronized 를 사용해 쓰레드가 공유하는 a 객체 자원을 동시에 사용하는
	// 경우를 방지한다, 만약 동시에 연산을 시작하려고 하면 쓰레드 연산에 순서를
	// 지정해준다
		for(int i=1; i<10; i++) {
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			System.out.println(i + " : sum : " + sum);
			sum += i;
		}
	}
}

public class Ex04 {
	public static void main(String[] args) {
		// 하나의 객체를 생성
		A04 a = new A04();
		Test04 t01 = new Test04(a, 1);
		Test04 t02 = new Test04(a, 2);
		Test04 t03 = new Test04(a, 3);
		System.out.println("t01 : " + t01);
		System.out.println("t02 : " + t02);
		System.out.println("t03 : " + t03);
		
		t01.start();
		t02.start();
		t03.start();
		
		/*
		A04 a1 = a;
		a.test();
		System.out.println(a1.sum);
		a1.test();
		System.out.println(a.sum);
		*/
		
		/*
		// !!!싱글톤 패턴 사용!!!
		// 생성된 객체를 공유
		// 즉 a 와 같은 공간을 공유!!!
		A04 a1 = a;
		
		System.out.println("a : " + a); // a : thread.A04@2133c8f8
		System.out.println("a1 : " + a1); // a1 : thread.A04@2133c8f8
		
		a1.sum = 12345;
		
		System.out.println(a.sum); // 12345
		System.out.println(a1.sum); // 12345
		*/
	}
}

synchronized - 동기화

- 쓰레드가 자원을 공유해서 사용할 때 동일한 시간에 동일한 공유 자원을 사용하면 문제가 발생하는데 이때 syncronized 즉, 동기화를 사용해 쓰레드가 동시에 공유 자원을 사용하는 순간 사용 순서를 지정해줘서 문제를 해결시켜준다.

 

 

동기화 ( synchronized ) 사용과 사용하지 않는 경우의 차이점

728x90

 

 

 

 

 

람다 ( Lambda )

람다 ( Lambda )

 

package lambda;

interface Test02{
	public void test02();
}

public class Ex02 {
	public static void main(String[] args) {
		
		// 인터페이스 자체를 객체화 할 수 있다
		// 인터페이스를 객체화 할 땐 메소드를 정의해줘야 한다
		Test02 t = new Test02() {
			@Override
			public void test02() {
				System.out.println("test 실행");
			}
		};
		t.test02(); // test 실행 출력
		
		System.out.println("--- 람다 ---");
		
		// 람다식 사용
		// () 의 의미는 Test02 의 메소드임을 의미
		// -> 를 사용하여 () 메소드의 내용을 우측에 정의
		// ★ 람다식을 사용할땐 무조건 메소드가 하나만 존재해야 한다 ★
		Test02 t02 = () -> System.out.println("test실행222");
		t02.test02(); // test실행222 출력
	}
}

람다식 사용법

 

package lambda;

interface Test03{
	public void test(int num, String msg);
}

public class Ex03 {
	public static void main(String[] args) {
		Test03 t = new Test03() {
			@Override
			public void test(int num, String msg) {
				System.out.println("num : " + num);
				System.out.println("msg : " + msg);
			}
		};
		t.test(100, "안녕하세요");
		// num : 100
		// msg : 안녕하세요
		
		System.out.println("--- 람다 ---");
		
		// 람다식 사용
		// 전달 받고자 하는 매개변수의 이름을 임의로 넣으면 됨
		Test03 t02 = (n, s) -> {
			System.out.println("n : " + n);
			System.out.println("s : " + s);
		};
		t02.test(500, "연습");
		// n : 500
		// s : 연습
	}
}

매개변수가 존재하는 인터페이스를 객체화할 때 람다식 사용법

 

package lambda;

interface Test04{
	public void test();
}

class TestClass04{
	// 인터페이스 객체를 변수로 받아 사용하는 메소드를 생성
	public void TestClass(Test04 t) {
		System.out.println("기능을 실행합니다!!!!!");
		t.test();
	}
}

public class Ex04 {
	public static void main(String[] args) {
		TestClass04 t01 = new TestClass04();
		
		// 람다식을 사용하여 인터페이스 객체화
		Test04 t04 = () -> System.out.println("test 실행됩니다");
		// 매개변수로 인터페이스 객체를 필요로 하는 메소드를 실행
		t01.TestClass(t04);
		// 기능을 실행합니다!!!!!
		// test 실행됩니다
		
		
		// 객체를 외부에 생성하지 않고 한 코드 안에서만 사용한 뒤
		// 버리는 경우 람다식을 사용해 간단하게 사용할 수 있다
		t01.TestClass(() -> {System.out.println("t1111111 실행");});
		// 기능을 실행합니다!!!!!
		// t1111111 실행
		// 위 문구 2줄 출력 후 생성되었던 인터페이스 객체는
		// 다음 코드로 넘어가면서 소멸된다
	}
}

람다식 사용 예시

( 인터페이스 객체를 매개변수로 요구하는 객체에 사용하는 경우 )

728x90

 

 

 

 

 

싱글톤 ( Singleton ) 패턴

싱글톤 ( singleton ) 패턴

 

싱글톤 패턴을 사용하는 방법

- 생성자 자체를 은닉화 ( private 을 사용하여 )

- 생성자를 은닉화 시키면 객체화하지 못하기 때문에 메소드를 public static 으로 선언하여 생성자를 메소드를 통해 생성할 수 있게함

- 이때 메소드에서 객체를 담을 변수를 사용하게 되는데 이 변수도 생성자를 사용하기 전에 메소드에서 사용되어야 함으로 static 을 사용하여 미리 클래스에 선언해줘야 함

728x90

 

 

 

 

 

추상 클래스 ( Abstract )

추상 클래스 ( Abstract )

 

package abstract_;

// 추상 메소드를 가진 추상 클래스임을 선언
abstract class Test01{
	// 추상 메소드임을 선언
	public abstract void speed();
	public void myBreak() {
		System.out.println("멈춤 기능");
	}
}

class TestClass01 extends Test01{
	// 상속한 Test01 클래스에 추상 메소드가 존재하므로
	// 무조건 오버라이딩을 진행해줘야 한다 ( 하지 않으면 컴파일 오류 발생 )
	public void speed() {
		System.out.println("2025년식 최고속도 : 250km");
	}
	public void autoSysem() {
		System.out.println("자동 운전 모드");
	}
}

class TestClass02 extends Test01{
	// 상속한 Test01 클래스에 추상 메소드가 존재하므로
	// 무조건 오버라이딩을 진행해줘야 한다 ( 하지 않으면 컴파일 오류 발생 )
	public void speed() {
		System.out.println("2026년식 최고속도 : 300km");
	}
	public void autoSysem() {
		System.out.println("자동 운전 모드");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		TestClass01 t = new TestClass01();
		t.speed();
		t.myBreak();
		t.autoSysem();
	}
}

※ 추상화를 사용하면 무조건 오버라이딩을 진행해야 한다 ※

추상화 클래스를 이용하는 경우 상속받았을때 무조건 오버라이딩을 상속 받는 클래스에 작성해야하기 때문에 다형성이 생긴다

 

 

 

 

 

 

 

 

 

 

인터페이스 ( interface )

인터페이스 ( interface ) - 변수에 static final 을 적지 않으면 default 로 적용된다

 

package interface_;

// 인터페이스 생성
interface A01{
	// 인터페이스의 메소드는는 {} 를 가지지 않는다
	public void test1();
}

// 인터페이스 생성
interface B01{
	// 인터페이스의 메소드는는 {} 를 가지지 않는다
	public void test1();
}

// 클래스 2개 생성
class Class01{}
class Class02{}

public class Ex01 extends Class01 implements A01, B01{
	// 인터페이스를 상속받을 경우 implements 를 사용
	// 인터페이스는 다중 상속이 가능하다!!!!
	
	@Override
	public void test1() {
		// 인터페이스에 test1() 추상 메소드가 존재한다
		// test1() 메소드를 선언하지 않으면 컴파일 오류가 발생한다
	}
}

인터페이스 코드 작성

 

인터페이스를 파일로 생성하여 상속

 

 

- 인터페이스를 사용하면 좋은 점 -

1. 메소드 이름을 단일화 할 수 있다 ( A 와 B 가 각자 개발해도 동일한 이름으로 기능을 다르게 개발 )

2. 인터페이스를 자료형으로 객체를 생성하여 내부에 담긴 인터페이스 메소드만 사용하거나 확인할 수 있다.

인터페이스 자료형으로 객체를 생성한 모습

728x90

 

 

 

부모형태에서 자식형태로 형변환 - 다운캐스팅

자식형태에서 부모형태로 형변환 - 업캐스팅

 

업캐스팅 ( upcasting )

package upcasting;

class A01{
	public void test() {
		System.out.println("aaaa");
	}
}
class B01 extends A01{
	public void test() {
		System.out.println("bbbb");
	}
}
class C01 extends A01{	
	public void test() {
		System.out.println("cccc");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		A01 a;
		// 자식 클래스를 부모 클래스 자료형 형태로 저장 = 업캐스팅
		a = new B01(); a.test(); // bbbb
		a = new C01(); a.test(); // cccc
		
		
		/*
		B01 b;
		C01 c;
		b = new B01(); // b 객체화
		c = new C01(); // c 객체화
		b.test(); // bbbb 출력
		c.test(); // cccc 출력
		*/
	}
}

업캐스팅 예시 ( 위와 같이 업캐스팅한 경우 부모 자료형 변수 a 에 자식 클래스를 객체화 시키면 메소드가 오버라이딩되기 때문에 자식 클래스의 메소드만 출력된다 )

 

package upcasting;

class Parents{
	public void famillyName() {
		System.out.println("이");
	}
	public void name() {
		famillyName();
		System.out.println("순신");
	}
}

class Daughter extends Parents{
	public void name() {
		famillyName();
		System.out.println("국주");
	}
}

class Son extends Parents{
	public void name() {
		famillyName();
		System.out.println("기광");
	}
}

public class Ex02 {
	public static void main(String[] args) {
		/*
		Parents par = new Parents();
		par.name();
		
		Daughter d = new Daughter();
		d.name();
		
		Son s = new Son();
		s.name();
		*/
		
		
		
		// 1번 아빠이름, 2번 딸이름, 3번 아들이름
		// 번호를 선택함에 따라 해당 이름이 나오게 세팅
		Parents par;
		// Daughter d;
		// Son s;
		
		// Daugter, Son 클래스의 부모클래스가 모두 Parents로 같으니
		// 번호 선택 시 부모 클래스 변수에 자식 클래스를 객체화하여 사용 ( 메소드 오버라이딩됨 )
		int num = 3;
		if(num == 1) {
			par = new Parents();
			par.name();
		}else if(num == 2) {
			par = new Daughter();
			par.name();
		}else if(num == 3) {
			par = new Son();
			par.name();
		}
	}
}

업캐스팅 사용 예시

 

 

 

 

 

 

 

 

 

 

다운캐스팅 ( downcasting )

package upcasting;

class Test{}

public class Ex03 {
	public static void main(String[] args) {
		// 업캐스팅 ( int, String 자료형을 부모 형태의 자료형에 저장 )
		Object num = 100;
		Object name = "홍길동";
		Object t = new Test();
		System.out.println(num.getClass()); // class java.lang.Integer
		System.out.println(name.getClass()); // class java.lang.String
		
		// 컴파일 오류 발생
		// 오버라이딩이 진행되어 num 변수의 자료형이 Object 로 변경되었기 때문
		// int a = 100 + num;
		
		// 다운캐스팅 ( Object 로 업캐스팅된 num 을 int 형으로 명시하여 다운캐스팅 )
		int a = 100 + (int)num;
		System.out.println(a);
	}
}

업캐스팅된 자료를 기존의 자료처럼 사용하려면 본인의 형태로 되돌리는 다운캐스팅 과정이 필요하다

728x90

 

 

 

 

 

오버라이딩 ( Overriding )

오버라이딩

 

package overriding;

class Ferrari{
	private int ye;
	public Ferrari(int ye) {
		this.ye = ye;
	}
	public int getYe() {
		return ye;
	}
	public void speed() {
		System.out.println(ye + "년식 페라리 속도 : 300km 달립니다");
	}
	public void onCar() {
		System.out.println("자동차 시동을 켭니다!!!");
	}
}

class NewFerrari extends Ferrari{
	public NewFerrari(int ye) {
		super(ye);
	}
	public void autoSystem() {
		// 페라리를 상속받아 새로운 메소드를 추가
		System.out.println("자동 운전모드를 실행합니다!!!");
	}
	public void speed() {
		// 부모의 speed() 메소드를 오버라이딩 ( overriding )
		// 오버라이딩 할 때는 접근제한자, 반환 자료형, 메소드명을 동일하게 해야한다
		// 또한 오버라이딩을 하는 자식 클래스의 접근제한자는 부모클래스보다 크거나 같아야한다
		System.out.println("500km 까지 달릴 수 있습니다!");
	}
}

public class Ex01 {
	public static void main(String[] args) {
		NewFerrari f = new NewFerrari(2024);
		f.onCar();
		f.speed();
		f.autoSystem();
	}
}

오버라이딩 ( Overriding ) 예시

1. 오버라이딩을 할 때는 자식 클래스의 접근제한자는 부모 클래스의 접근 제한자보다 크거나 같아야 한다.

2. 오버라이딩 시 부모가 가지고 있는 메소드와 ( 접근 제한자, 반환 자료형, 메소드 이름 ) 이 동일해야 한다

 

package overriding;

import java.util.ArrayList;

class Test02 extends ArrayList<String>{
	// ArrayList 를 상속
	
	// get() 메소드 오버라이딩
	public String get(int i) {
		System.out.println( super.get(i) );
		return super.get(i);
	}
}

public class Ex02 {
	public static void main(String[] args) {
		Test02 t = new Test02();
		t.add("111");
		t.add("222");
		t.add("333");
		
		// 기존의 get() 메소드는 String 형태로 값을 반환만 해줌, 출력 X
		// get() 메소드를 오버라이딩하여 해당 값을 바로 출력하게끔 변경
		t.get(2);
		// 3 출력
	}
}

ArrayList 오버라이딩 예시

( 오버라이딩 코드에서 프린팅 값과 return 값에 super. 를 사용하지 않으면 자기 자신의 메소드가 재실행 되므로 무한으로 코드가 재실행되어 StackOverflowError 가 발생하기 때문에 super. 를 사용하여 부모 클래스의 값을 호출하여 사용한다.

 

 

 

 

 

final

package overriding;

final class Test03{
	public void test() {
		System.out.println("test03의 test 기능");
	}
}

class TestClass03 { // extends Test03 불가
	// 에러 발생 final 클래스는 상속을 받을 수 없음
	public void test() {
		System.out.println("Testclass03의 test 기능");
	}
}

public class Ex03 {
	public static void main(String[] args) {
		TestClass03 t = new TestClass03();
		Test03 t3 = new Test03();
		// final 이 붙은 클래스는 상속을 받아 사용할 수 없으므로
		// 객체화하여 사용해야 한다
		
		t3.test();
	}
}

final 을 붙이는 경우 상속, 오버라이딩 등을 변경할 수 없는 상태가 된다

위에서 만약 TestClass03 클래스가 Test03 클래스를 상속 받으려고 extends Test03 을 입력하면 컴파일 오류가 출력된다

 

package overriding;

class Test04{
	// 메소드의 접근제한자가 protected
	protected void test() {
		System.out.println("부모 실행");
	}
}

class TestClass04 extends Test04{
	// test() 메소드 오버라이딩된 상태
	// 부모 클래스의 test() 메소드가 protected 이며 오버라이딩
	// 접근제한자로 설정한 것이 public 이므로 부모의 접근제한자보다
	// 크기 때문에 오버라이딩이 가능하다
	// 만약 부모 클래스의 접근제한자보다 작다면 오버라이딩이 불가하다 ( 컴파일 오류 )
	public void test() {
		System.out.println("자식 실행");
	}
}

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

오버라이딩 시 접근제한자는 오버라이딩 하려는 부모 클래스의 메소드보다 무조건 커야한다

 

package overriding;

class TestDTO{
	String name;
	int age;
	
	// toString() 메소드를 오버라이딩
	// 저장된 공간이 출력되는 toString() 메소드는 자체로
	// 사용할 일이 많이 없기 때문에 오버라이딩하여 사용하는 경우가 많다
	@Override
	public String toString() {
		return "[name : " + name + ", age = " + age + "]";
	}
}

class Test06{
	TestDTO t;
	// 생성자
	public Test06() { t = new TestDTO(); }
	
	// 메소드
	public void setDTO() { 
		t.name = "홍길동";
		t.age = 200;
	}
	
	public void print() {
		System.out.println(t.name);
		System.out.println(t.age);
		System.out.println("------------------");
		System.out.println(t.toString());
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
		System.out.println(t);
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
	}
}

public class Ex06 {
	public static void main(String[] args) {
		Test06 t = new Test06();
		t.setDTO();
		
		t.print();
		// 오버라이딩 전 : overriding.TestDTO@43a25848
		// 오버라이딩 후 : [name : 홍길동, age = 200]
	}
}

toString() 메소드를 오버라이딩

toString 메소드는 모든 자료에 다 내재되어 있으며 해당 메소드를 사용하면 저장된 메모리 공간이 출력된다, 하지만 이 기능을 사용할 일이 없으므로 오버라이딩하여 많이 사용하며 해당 메소드 오버라이딩은 DTO 클래스에서 진행하는 경우가 많다

728x90

 

 

 

 

 

예외 처리 ( Exception )

예외 처리

 

 

package exception;

import java.util.Scanner;

public class Ex01 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int x, y, result = 0;
		System.out.print("수 입력 : ");
		x = input.nextInt();
		System.out.print("수 입력 : ");
		y = input.nextInt();
		try {
			result = x / y ;
			// try 코드에서 문제가 발생하면 catch 로 넘어간다
			// try 에서 문제가 없다면 catch 를 진행하지 않고 다음 코드로 넘어간다
		}catch(ArithmeticException e) {
			// 0 으로는 나눌 수 없는 예외를 처리
			System.out.println("문제 발생");
			System.out.println("0으로 나눌 수 없음");
		}
		System.out.println("결과 : " + result);
	}
}

발생하는 예외와 일치하는 예외로 처리해줘야 한다

( 예외 클래스들의 부모 클래스인 Exception 으로 통합하여 예외처리도 가능하다 )

 

package exception;

import java.util.Scanner;

public class Ex02 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		int num;
		while(true) {
			System.out.print("수 입력 : ");
			num = input.nextInt();
			try {
				System.out.println("결과 : " + (100/num));
			} catch(Exception e) {
				// Exception 은 예외들의 부모 클래스
				System.out.println(e);
				System.err.println("에러 : " + e); // 빨간 글씨로 출력
				// java.lang.ArithmeticException: / by zero
				// 에러 : java.lang.ArithmeticException: / by zero
			}
		}
	}
}

예외 처리 예시

 

package exception;

import java.util.ArrayList;

public class Ex03 {
	public static void main(String[] args) {
		
		ArrayList<String> arr = new ArrayList<>();
		arr.add("111"); // index : 0
		arr.add("222"); // index : 1
		arr.add("333"); // index : 2
		for(int i=0; i<=arr.size(); i++) {
			// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
			// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
			// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
			try {
				System.out.println(arr.get(i));
			} catch(IndexOutOfBoundsException e) {
				System.out.println(e);
				// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
			}
		}
		System.out.println("다음 문장 실행!!!");
	}
}

예외 처리 예시

 

package exception;

import java.util.ArrayList;

public class Ex03 {
	public static void main(String[] args) {
		
		ArrayList<String> arr = new ArrayList<>();
		arr.add("111"); // index : 0
		arr.add("222"); // index : 1
		arr.add("333"); // index : 2
		for(int i=0; i<=arr.size(); i++) {
			// arr.size 의 크기와 같아지면 index(3) 까지 출력 명령이 들어가는데
			// 이때 해당 인덱스에 값이 없기 때문에 오류 출력
			// 이때 예외가 발생되는 문장을 콘솔창에서 찾아 try / catch 사용
			try {
				int n1 = 10, n2 = 0;
				System.out.println(n1/n2);
				
				System.out.println(arr.get(i));
			} catch(IndexOutOfBoundsException e) {
				System.out.println(e);
				// java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
			} catch(ArithmeticException e) {
				System.out.println(e);
				// java.lang.ArithmeticException: / by zero
			}
		}
		System.out.println("다음 문장 실행!!!");
	}
}

예외 처리는 오버라이드 ( override ) 를 사용하여 각자 발생하는 예외를 매개변수로 갖는 메소드로 향하게 설정이 가능하다

 

package exception;

import java.util.Scanner;

public class Ex05 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int x;
		System.out.println("수 입력");
		x = sc.nextInt();
		
		try {
			int result = 10 / x;
			System.out.println("결과 : " + result);
			return;
		}catch (Exception e) {
			// 예외가 발생된 내용을 자세하게 출력
			e.printStackTrace();
		}finally {
			// finally 는 try 가 실행되든지 catch 가 실행되든지
			// 무조건 실행되는 코드
			// return 으로 해당 코드를 종료해도 finally 는 무조건적으로 실행된다
			System.out.println("finally 실행");
			sc.close();
			// finally 를 사용하여 Scanner 스트림을 무조건 종료시키는 코드 실행
		}
		System.out.println("다음 문장들 실행!!!");
	}
}

e.printStackTrace(); - 예외의 자세한 내용을 출력

finally - 예외가 발생되던지 발생되지 않던지 해당 코드는 진행이 된다

( finally 는 try/catch 에만 사용할 수 있는 것이 아니므로 꼭 실행해야 하는 코드가 있다면 finally 처리를 해주면 된다 )

 

 

 

 

 

예외 전가

package exception;

public class Ex07 {
	public static void main(String[] args) throws InterruptedException {
										// 예외 전가를 사용하여 예외 처리
		
		// 예외처리를 해줘야 하는 Thread.sleep(); 메소드
		// 예외처리 해주지 않으면 컴파일 오류가 발생한다
		Thread.sleep(1000);
	}
}

예외 전가

 

package exception;

class Test06{
	public void test1() throws InterruptedException {
		System.out.println("1111");
		// test2() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
		test2();
	}
	public void test2() throws InterruptedException {
		System.out.println("2222");
		// 첫 예외 발생 > throws 로 예외 전가
		Thread.sleep(1000);
	}
}

public class Ex06 {
	public static void main(String[] args) throws InterruptedException {
		Test06 t = new Test06();
		// t.test1() 메소드에서 예외를 전가당했으므로 예외가 발생 > throws 로 예외 전가
		t.test1();
		// 1111
		// 2222
	}
}

예외 전가의 문제점

( 메소드를 호출하여 사용할때 해당 메소드에서 예외를 전가했다면 호출한 클래스에서도 예외를 처리해줘야 한다 )

( 만약 최초 예외가 발생된 곳에서 try / catch 로 개별로 예외를 처리해줬다면 해당 메소드를 호출해도 호출한 클래스에서는 예외가 발생하지 않는다 )

 

 

 

 

 

강제 예외

package exception;

import java.util.Scanner;

public class Ex08 {
	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int age = 0;
		System.out.print("나이 입력 : ");
		try {
			age = sc.nextInt();
			if(age < 0) {
				throw new Exception("음수는 입력불가!!!");
			}
			
		} catch (Exception e) {
//			e.printStackTrace();
			System.out.println(e.getMessage());
		}
		System.out.println("당신의 나이는 : " + age);
	}
}

수를 음수로 입력받으면 강제로 예외로 던지는 형태

728x90

+ Recent posts