본문 바로가기
JAVA

2022-10-18 객체지향언어 - 인터페이스, 예외처리방법 1. try-catch / 2. 예외선언하기(throw, throws)

by HTT 2022. 10. 22.

인터페이스

 



: 추상메소드만 보관하는 특별한 클래스
  => 인터페이스를 사용하면 다형성을 적용할 수 있으며 다중상속 받은 것처럼 구현할 수 있다.

 

1. 인터페이스는 정의할 때 interface키워드를 이용해서 정의

2. 인터페이스는 추상메소드만 정의할 수 있다.

   - 인터페이스에 정의하는 모든 메소드는 public abstract을 생략해도 된다.
   - 멤버변수는 상수로 public static final이다.
   - 하위클래스에서 오버라이딩하면 자동으로 public이 추가된다.
3. 클래스가 인터페이스를 상속할 때는 implements로 상속(구현)

4. 인터페이스가 인터페이스를 상속할 수 있다.
   - 인터페이스가 인터페이스를 상속하는 경우 extends를 이용

5. 클래스가 인터페이스를 상속하는 경우에는 다중상속이 가능하다. 즉, 여러 개의 인터페이스를 상속할 수 있다.
   - 로 구분해서 정의
   - 인터페이스가 인터페이스를 상속하는 경우에도 다중상속을 허용

6. 클래스와 인터페이스를 모두 상속하는 경우 extends가 implements보다 먼저 선언되어야 한다.

 

 

interface SuperInterfaceA{
	void show(); // 인터페이스가 갖는 추상메소드
}
interface InterA extends SuperInterfaceA{
	void test();
	void display();
}
interface InterB{
	void change();
}
interface InterC extends InterA, InterB{
	// InterC 인터페이스는 show, test, display, change 다 갖고 있음
}
class SuperObj{
	
}
class TestA extends SuperObj implements InterA, InterB{  //6번
	// InterA, InterB를 상속하면 TestA는 추상클래스가 된다 - 추상메소드를 모두 오버라이딩해야 한다.
	@Override
	public void show() {
		
	}
	@Override
	public void change() {
		
	}
	@Override
	public void test() {
		
	}
	@Override
	public void display() {
	
	}
}

public class InterfaceTest2 {

	public static void main(String[] args) {

	}
}
// 자세히 보기
class Parant{
	
}
class A extends Parant{
	
}
class B extends Parant{
	
}
class C extends Parant implements Group1{
	
}
class D extends Parant implements Group1{
	
}
interface Group1{
	
}
class Test{
	// A,B,C,D는 Parant의 하위
	public void run(Parant obj) {
		
	}
	// C,D는 Parant와 Group1을 모두 상위로 갖는다.
	public void test(Group1 obj) {
		
	}
	public void exam(Group1 obj){
		
	}
}

public class InterfaceTest {
	public static void main(String[] args) {
		Test test = new Test();
		// 생성된 A,B,C,D객체를 메인메소드 내부에서 사용하지 않고 run메소드에서만 사용하면 참조 변수를 정의해서 사용하지 않고
		// 바로 객체를 생성해서 매개변수로 전달해도 된다.
		A obj = new A();
		test.run(obj);
		test.run(new B());
		test.run(new C());
		test.run(new D());
		test.exam(new C());
		test.exam(new D());
	}

}

 

 

 

 

 

 

 


예외처리

 


try-catch

 

순서

 

1. 예외 발생

 

2. 해당 예외객체가 메모리에 생성됨(heap) -> 객체가 만들어져서 전달됨

 

3. catch블럭의 예외변수에 할당됨

 

4. try블럭의 실행이 멈추고 catch블럭으로 이동되어 코드가 실행됨

 

 

 

* try~catch

public class ExceptionTest02 {
	public static void main(String[] args) {
		try {
			// 예외발생 가능성이 있는 코드
			System.out.println("try블럭시작");
			// Exception 발생하면 더 이상 try블럭안의 코드를 실행하지 않고 catch블럭으로 이동함
			//System.out.println(args[0]);
			System.out.println(10/0);
			System.out.println("try종료");
		}catch(Exception e) {
			// 예외가 발생하면 처리할 문장을 구현
			System.out.println("예외발생함");
		}
	}
}

 

 

* try~catch~catch...

   => catch블럭을 다중 선언하고 사용하는 것은 가능하나, 상위 Exception클래스보다 하위 Exception클래스를 먼저 정의해야 한다.

public class ExceptionTest03 {
	public static void main(String[] args) {
		Scanner key = new Scanner(System.in);
		try {
			// 예외발생 가능성이 있는 코드
			System.out.println("시작");
			System.out.println("숫자입력");
			System.out.println(Integer.MAX_VALUE); //1231231232133
			int num1 = key.nextInt();
			System.out.println("나눌 숫자를 입력");
			int num2 = key.nextInt();
			System.out.println("결과=>"+(num1/num2));
			System.out.println("종료");
		}catch(ArithmeticException e) {
			System.out.println("0으로 나눴음. 다시 입력하기");
		}catch(InputMismatchException e) {
			System.out.println("숫자가 아님. 다시 입력해라");
		}catch(Exception e) {
			System.out.println("예외발생");
			System.out.println("예외메세지=>"+e.getMessage());
			// 개발 시에 가장 많이 사용함 -
			// 여러 클래스를 이용해서 사용하는 경우 오류를 추적해서 어떤 클레스에서 예외가 발생하는지 확인하는 것이 가능
			e.printStackTrace();
		}
	}
}

 

 

* tryAcatch~finally

   => 예외가 발생하거나 발생하지 않거나 반드시 실행해야 하는 코드가 있는 경우 finally블럭에 정의한다.

public class ExceptionTest04 {
	public static void main(String[] args) {
		Scanner key = new Scanner(System.in);
		try {
			// 예외발생 가능성이 있는 코드
			System.out.println("시작");
			System.out.println("숫자입력");
			System.out.println(Integer.MAX_VALUE); //1231231232133
			int num1 = key.nextInt();
			
			System.out.println("나눌 숫자를 입력");
			int num2 = key.nextInt();
			System.out.println("결과=>"+(num1/num2));
			System.out.println("종료");
		}catch(ArithmeticException e) {
			System.out.println("0으로 나눴음. 다시 입력하기");
		}catch(InputMismatchException e) {
			System.out.println("숫자가 아님. 다시 입력해라");
		}catch(Exception e) {
			System.out.println("예외발생");
			System.out.println("예외메세지=>"+e.getMessage());
			// 개발 시에 가장 많이 사용함 - 
			// 여러 클래스를 이용해서 사용하는 경우 오류를 추적해서 어떤 클레스에서 예외가 발생하는지 확인하는 것이 가능
			e.printStackTrace();
		}finally {
			System.out.println("무조건 실행되는 코드 ---------------- 자원반납");
		}
	}
}

 

 

 

예외 선언하기 throw, throws

 

=> 예외 떠넘기기(알리기)

 

- throw : 예외를 발생시키는 키워드

  throws : 예외를 메서드에 선언할 때 사용

 

 

- 처리 방법

 

1. 예외가 발생하는 곳에서 예외에 대한 처리를 구현

2. 예외를 발생하는 곳에서 처리하지 않고 호출한 곳에서 처리

public class ThrowsExceptionTest01 {
	// 1. 예외가 발생하는 곳에서 예외에 대한 처리를 구현
	public void test(String fileName) { 
		try {
		FileReader fr = new FileReader(fileName); // 에러발생코드
		}catch(FileNotFoundException e) {
			System.out.println("예외처리작업...완료");
		}
	}
	// 2. 예외를 발생하는 곳에서 처리하지 않고 호출한 곳에서 처리
	public void test2(String fileName) throws FileNotFoundException{ 
		FileReader fr = new FileReader(fileName); // 에러발생코드
		
	}
	
	public static void main(String[] args) {
		ThrowsExceptionTest01 obj = new ThrowsExceptionTest01();
		//1. 예외를 예외가 발생한 메소드 내부에서 처리하고 있으므로 호출한 곳에서는 예외 발생 유무를 확인할 수 없다.
        
		// test메소드를 A위치에서 호출함 - A클래스의 a메소드에서 호출한다 가정
		obj.test("test2.txt");
		// test메소드를 B위치에서 호출 - B클래스의 b메소드에서 호출한다 가정
		obj.test("test2.txt");
        
		//2. 예외를 호출한 곳(main)에서 처리
		//test2메소드를 A위치에서 호출 - A클래스의 a메소드에서 호출한다 가정
		try{
			obj.test2("test2.txt");  //에러발생코드를 실행 => 에러발생함
		}catch(FileNotFoundException e) {
			System.out.println("파일명을 다시 선택하세요.=====> 선택할 수 있는 코드를 작성");
		}
		// test2메소드를 B위치에서 호출 - B클래스의 b메소드에서 호출한다 가정
		try{
			obj.test2("test2.txt");
		}catch(FileNotFoundException e) {
			System.out.println("test.txt로 작업할 수 있도록 파일을 정의");
		}
	}
}

 

 

public class MyException extends Exception{
	public MyException(String msg) {
		super(msg); // Exception클래스의 메세지를 전달 - Exception의 매개변수 1개 생성자를 호출
	}
}


public class MyExceptionTest {

	public static void main(String[] args) {
		System.out.println("프로그램시작");
		System.out.println("스텝1");
		System.out.println("스텝2");
		System.out.println("스텝3");
		Scanner key = new Scanner(System.in);
		System.out.println("숫자를 입력하세요");
		int num = key.nextInt();
		if(num%2==1) {
			//홀수가 입력되어지면 예외상황으로 간주 - 예외를 인위적으로 발생시킴
			try {
				throw new MyException("홀수가 입력되었습니다.(error)"); //에러발생코드
			
			}catch(Exception e) {
				System.out.println("예외처리 완료");
				System.out.println("----------------------");
				System.out.println(e.getMessage());
			}
		}else {
			System.out.println("정상스텝");
		}
	}
}

 

 

 

- 예외 종류

import java.io.FileReader;
import java.util.Scanner;
class Super{
	
}
class Sub extends Super{
	
}

public class ExceptionTest01 {
	public static void main(String[] args) {
    
		// 1. 개발자가 실수할 수 있는 부분-------------------------------------------------------
		System.out.println("***********프로그램 시작************");
		//System.out.println(10/0);  //ArithmeticException
		//System.out.println(args[0]);  //ArrayIndexOutOfBoundsException
		String str = null;  // 참조변수가 null인데 메소드를 호출해서 사용하는 경우
		//str.length();  // NullPointerException
		Super obj = new Super();
		//Sub obj1 = (Sub)obj; // 변환할 수 없는 타입으로 강제 형변환하는 경우 - ClassCastException
		
		//2. 외부 요인이나 사용자의 실수로 예외가 발생하는 경우
		Scanner key = new Scanner(System.in);
		System.out.println("값을 입력하세요:");
		int data = key.nextInt();
		System.out.println("입력하신 데이터는=>"+data);
		
		// 3. API에서 문법적으로 예외처리를 요구하는 경우
		// RuntimeException의 하위 Exception은 문법적으로 예외에 대한 처리를 하지 않아도 되지만 해야 한다.
		// 나머지 Exception은 예외처리를 하지 않으면 컴파일오류가 발생하므로 해야 한다.
		FileReader fr = new FileReader("test.txt");
		Integer.parseInt("100");
	}

}

 

 

 

<예제>

문자열을 입력받아 숫자로 변환하기(에외발생 시 메세지 출력)

import java.util.Scanner;
public class ExceptionExam02 {
	
	public static void main(String[] args) {
		//필요할 경우 다음의 메서드 선언부분(메서드 시그너처)을 수정하시기 바랍니다.
		ExceptionExam02 obj = new ExceptionExam02();
		Scanner scan= new Scanner(System.in);
		System.out.println("숫자로 변환할 문자열을 입력바랍니다.");
		String str= scan.nextLine();
		int result= 0;
		//여기를 작성하십시오.
		try {
			result = convert(str);
			System.out.println("변환된 숫자는 "+result+" 입니다.");
		}catch(IllegalArgumentException e){
			System.out.println("예외가 발생되었습니다. 문자열을 입력하지 않고 엔터를 누르셨습니다.");
			e.printStackTrace();
		}
		
		
	}
	
	//필요할 경우 다음의 메서드 선언부분(메서드 시그너처)을 수정하시기 바랍니다.
	private static int convert(String str) throws IllegalArgumentException{ // throws IllegalArgumentException 문법적으로 쓰지 않아도 됨
										// ㄴ> RuntimeException의 하위이기 때문에 쓰지 않아도 문법적으로 허용됨
		int result = 0;
		if(str == null || str.length() == 0){
			throw new IllegalArgumentException();
		}
		result = Integer.parseInt(str);
		return result;
	}
}

댓글