NetworkClient
: 외부 서버와 연결하고, 데이터를 전송 및 연결을 종료하는 기능을 제공NetworkService
: NetworkClient
를 사용해서 데이터를 전송한다. NetworkClient
를 사용하ㅁ려면 연결, 전송 , 연결 종료와 같이 복잡한 흐름을 제어해야 하는데 이런 부분은 서비스가 담당함Main
: 사용자의 입력을 받는다.Main
을 통해 사용자의 입력을 받으면 사용자의 입력을 서비스에 전달한다.NetworkService
는 NetworkClient
를 사용해서 외부 서버에 연결하고, 데이터를 전송하고, 전송이 완료되면 연결을 종료한다. package exception.ex0;
public class NetworkClientV0 {
private final String address;
public NetworkClientV0(String address) {
this.address = address;
}
public String connect() { //연결 성공
System.out.println(address + " 서버 연결 성공");
return "success";
}
public String send(String data) { //전송 성공
system.out.println(address + " 서버에 데이터 전송: " + data);
return "success";
}
public void disconnect() {
System.out.println(address + " 서버 연결 해제");
}
}
String address
: 접속할 외부 서버 주소connect()
: 외부 서버에 연결한다send(String data)
: 연결한 외부 서버에 데이터를 전송한다.disconnect()
: 외부 서버와 연결을 해제한다.package exception.ex0;
import java.util.Scanner;
public class MainV0 {
public static void main(String[] args) {
NetworkServiceV0 networkService = new NetworkServiceV0();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("전송할 문자: ");
String input = scanner.nextLine();
if (input.equals("exit")) {
break;
}
networkService.sendMessage(input);
System.out.println();
}
System.out.println("프로그램을 정상 종료합니다."); }
}
Scanner
를 통해서 입력받는다.NetworkService.sendMessage()
를 통해 메시지를 전달한다.exit
를 입력하면 프로그램을 정상 종료한다.package exception.ex1;
public class NetworkClientV1 {
private final String address;
public boolean connectError;
public boolean sendError;
public NetworkClientV1(String address) {
this.address = address;
}
public String connect() {
if (connectError) {
System.out.println(address + " 서버 연결 실패");
return "connectError";
}
//연결 성공 System.out.println(address + " 서버연결 성공");
return "success";
}
public String send(String data) {
if (sendError) {
System.out.println(address +"서버에 데이터 전송 실패: " + data);
return "sendError";
}
System.out.println(address + "서버에 데이타 전송: " + data);
return "success";
}
public void disconnect() {
System.out.println(address + "서버 연결해제");
}
public void initError(String data) {
if (data.contains("error1")) {
connectError = true;
}
if (data.contains("error2")) {
sendError = true;
}
}
}
sendError
: 이 필드의 값이 true
가 되면 연결에 실패하고 connectError
오류 코드를 반환한다.connectError
: 이 필드의 값이 true
가 되면 데이터 전송에 실패한다. sendError
오류 코드를 반환한다.success
코드를 반환한다.initError(String data)
connectError
,sendError
필드의 값을 true
로 설정할 수 있다.connectError
오류가 발생하고 "error2"가 있으면 sendError
오류가 발생한다.package exception.ex1;
public class NetworkServiceV1_1 {
public void sendMessage(String data) {
String address = "http://example.com";
NetworkClientV1 client = new NetworkClientV1(address);
client.initError(data); //추가
client.connect();
client.send(data);
client.disconnect();
}
}
package exception.ex1;
import java.util.Scanner;
public class MainV1 {
public static void main(String[] args) {
NetworkServiceV1_1 networkService = new NetworkServiceV1_1();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("전송할 문자: ");
String input = scanner.nextLine();
if (input.equals("exit")) {
break;
}
networkService.sendMessage(input);
System.out.println();
}
System.out.println("프로그램을 정상 종료합니다.");
}
}
public class NetworkServiceV1_3 {
public void sendMessage(String data) {
NetworkClientV1 client = new NetworkClientV1("http://example.com");
client.initError(data);
String connectResult = client.connect();
if (isError(connectResult)) {
System.out.println("[네트워크 오류 발생] 오류 코드: " + connectResult);
}
else {
String sendResult = client.send(data);
if (isError(sendResult)) {
System.out.println("[네트워크 오류 발생] 오류 코드: " + sendResult);
}
}
client.disconnect();
}
private static boolean isError(String resultCode) {
return !resultCode.equals("success");
}
}
disconnect()
를 호출disconnect()
를 호출자바는 프로그램 실행 중에 발생 할 수 있는 예상치 못한 상황, 예외를 처리하기 위한 메카니즘을 제공한다.
Object
: 자바에서 기본형을 제외한 모든 것은 객체다.Throwable
: 최상위 예외이다.Error
: 메모리 부족이나 심각한 시스템 오류와 같이 애플리케이션에서 복구가 불가능한 시스템 예외이다. 애플리케이션 개발자는 이 예외를 잡으려고 해서는 안된다.Exception
: 체크예외RuntimeException
은 예외로 한다.RuntimeException
:언체크 예외RuntimeException
과 그 자식 예외는 모두 언체크 예외이다.RuntimeException
의 이름을 따라서 RuntimeException
과 그 하위 언체크 예외를 런타임 예외라고 많이 부른다. 체크 예외 VS 언체크 예외
체크 예외는 발생한 예외를 개발자가 명시적으로 처리해야한다. 그렇지않으면 컴파일 오류가 발생한다. 언체크 예외는 개발자가 예외를 명시적으로 처리하지 않아도 된다.
Exception
을 catch
로 잡으면 그 예외의 자식들도 함께 처리할 수 있다.Exception
을 throws
로 던지면 그 하위 예외들도 모두 던질 수 있다.package exception.basic.checked;
/**
* Exception을 상속받은 예외는 체크 예외가 된다. */
public class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
}
}
Exception
을 상속받은 예외는 체크 예외가 된다.package exception.basic.checked;
public class Client {
public void call() throws MyCheckedException {
throw new MyCheckedException("ex");
}
}
throw 예외
라고 하면 새로운 예외를 발생 시킬 수 있다. 예외는 객체이기 때문에 먼저 new로 생성하고 예외를 발생시켜야 한다.throws 예외
는 발생시킨 예외를 메서드 밖으로 던질 때 사용하는 키워드이다.package exception.basic.checked;
/**
* Checked 예외는
* 예외를 잡아서 처리하거나, 던지거나 둘중 하나를 필수로 선택해야 한다. */
public class Service {
Client client = new Client();
/**
* 예외를 잡아서 처리하는 코드 */
public void callCatch() {
try {
client.call();
} catch (MyCheckedException e) {
//예외 처리 로직
System.out.println("예외 처리, message=" + e.getMessage()); }
System.out.println("정상 흐름");
}
/**
* 체크 예외를 밖으로 던지는 코드
* 체크 예외는 예외를 잡지 않고 밖으로 던지려면 throws 예외를 메서드에 필수로 선언해야한다. */
public void callThrow() throws MyCheckedException {
client.call();
}
}
callCatch()
: Client
에서 던진 오류를 try-catch로 잡는 메서드try
에서 잡은 예외가 catch
의 대상에 없다면 예외를 잡을 수 없다.package exception.basic.checked;
public class CheckedThrowMain {
public static void main(String[] args) throws MyCheckedException {
Service service = new Service();
service.callThrow();
System.out.println("정상 종료");
}
}
callThrow()
: Client
에서 던진 오류를 잡지 않고 메서드 밖으로 던짐
main()
메서드까지 올라갈 수 있다.main()
밖으로 던져져, service.callThrow()
메서드 다음에 있는 "정상 종료"가 출력되지 않는다.체크 예외의 장단점
장점: 개발자가 실수로 예외를 누락해도 컴파일러를 통해 문제를 잡을 수 있는 훌륭한 안전장치이다.
단점: 모든 체크 예외를 반드시 잡거나 던지도록 처리해야한다.
체크 예외 VS 언체크 예외
throws
키워드를 사용해서 던지는 예외를 선언해야 한다.throws
키워드를 생략할수 있다. package exception.basic.unchecked;
/**
* RuntimeException을 상속받은 예외는 언체크 예외가 된다. */
public class MyUncheckedException extends RuntimeException {
public MyUncheckedException(String message) {
super(message);
}
}
package exception.basic.unchecked;
public class Client {
public void call() {
throw new MyUncheckedException("ex");
}
}
package exception.basic.unchecked;
/**
* UnChecked 예외는
* 예외를 잡거나, 던지지 않아도 된다.
* 예외를 잡지 않으면 자동으로 밖으로 던진다. */
public class Service {
Client client = new Client();
/**
* 필요한 경우 예외를 잡아서 처리하면 된다. */
public void callCatch() {
try {
client.call();
} catch (MyUncheckedException e) {
//예외 처리 로직
System.out.println("예외 처리, message=" + e.getMessage());
}
System.out.println("정상 로직");
}
/**
* 예외를 잡지 않아도 된다. 자연스럽게 상위로 넘어간다.
* 체크 예외와 다르게 throws 예외 선언을 하지 않아도 된다. */
public void callThrow() {
client.call();
}
}
언체크 예외의 장단점
throws
의 생략이 가능하다.