Loading the catalog…
Loading the catalog…
문법만 알고 프로그램을 만들면 곧 세 가지 현실적인 문제를 만나게 된다. 예상하지 못한 입력이나 오류가 발생한다. 여러 작업을 동시에 처리해야 한다. 콘솔이나 파일처럼 프로그램 외부와 데이터를 주고받아야 한다. Java에서는 각각 예외 처리 , 스레드 , 입출력 API 로 대응한다. 1. 예외는 프로그램 실행 중 발생하는 문제 상황이다 예를 들어 존재하지 않는 배열 인덱스에 접근하면 예외가 발생한다. int[] values = {10, 20, 30}; System.out.println(values[5]); 프로그램에서 예상 가능한 문제를 처리하려면 try-catch 를 사용한다. try { int[] values = {10, 20, 30}; System.out.println(values[5]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("잘못된 인덱스입니다."); } 가능하면 무조건 Exception 하나로 잡기보다 처리할 수 있는 구체적인 예외 를 잡는 편이 의도가 명확하다. 2. 여러 catch 로 예외 종류를 나누기 try { int page = Integer.parseInt(input); System.out.println(values[page]); } catch (NumberFormatException e) { System.out.println("숫자 형식이 아닙니다."); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("범위를 벗어났습니다."); } 예외 종류에 따라 다른 복구 전략을 적용할 수 있다. 3. throw : 의도적으로 예외 발생시키기 잘못된 상태를 그냥 통과시키지 않고 예외로 표현할 수 있다. public static void validateAmount(int amount) { if (amount < 0) { throw new IllegalArgumentException("금액은 0 이상이어야 합니다."); } } 이렇게 하면 호출하는 쪽에서 오류를 명확하게 인식할 수 있다. 4. finally : 성공해도 실패해도 실행 try { System.out.println("작업 시작"); } catch (Exception e) { System.out.println("문제 발생"); } finally { System.out.println("작업 종료"); } finally 는 예외 발생 여부와 관계없이 실행된다. 과거에는 파일이나 네트워크 자원을 닫는 데 많이 사용했지만, 닫을 수 있는 자원은 try-with-resources 가 더 안전한 경우가 많다. 5. try-with-resources AutoCloseable 을 구현한 자원은 블록이 끝날 때 자동으로 닫힌다. import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; try (BufferedWriter writer = new BufferedWriter(new FileWriter("app.log"))) { writer.write("application started"); } catch (IOException e) { System.out.println("파일 저장 실패"); } 정상 종료뿐 아니라 예외가 발생한 경우에도 close() 가 호출되므로 자원 누수를 줄일 수 있다. 6. 사용자 정의 예외 도메인에 맞는 오류 의미를 표현하고 싶다면 직접 예외 클래스를 만들 수 있다. class InsufficientStockException extends Exception { public InsufficientStockException(String message) { super(message); } } public static void validateStock(int stock, int quantity) throws InsufficientStockException { if (stock < quantity) { throw new InsufficientStockException("재고가 부족합니다."); } } 7. throws : 예외 처리를 호출한 곳으로 넘기기 public static String loadConfig() throws IOException { // 파일 읽기 return "config"; } 메소드가 직접 해결하기 어려운 예외를 상위 호출자에게 맡길 수 있다. throw 는 예외를 실제로 발생시키는 것 , throws 는 이 메소드가 예외를 바깥으로 전달할 수 있음을 선언하는 것 이다. 8. 스레드란? 스레드는 하나의 프로세스 안에서 실행되는 작업 흐름이다. 여러 스레드를 사용하면 여러 작업이 동시성(concurrency) 을 가지게 할 수 있다. 여러 CPU 코어에서 실제로 동시에 실행될 수도 있지만, 스레드를 만들었다고 항상 물리적으로 병렬 실행되는 것은 아니다. 스케줄러와 실행 환경에 따라 달라진다. Thread 상속 class LogThread extends Thread { @Override public void run() { for (int i = 1; i <= 3; i++) { System.out.println("log " + i); } } } Thread thread = new LogThread(); thread.start(); run() 을 직접 호출하는 것과 start() 는 다르다. 새 스레드에서 실행하려면 start() 를 호출해야 한다. 9. Runnable 구현 동작을 객체로 분리하려면 Runnable 을 사용할 수 있다. Runnable task = () -> { for (int i = 1; i <= 3; i++) { System.out.println("task " + i); } }; Thread thread = new Thread(task); thread.start(); Thread 를 직접 상속하지 않으므로 다른 클래스를 상속해야 하는 경우에도 사용할 수 있다. 실무에서는 낮은 수준의 Thread 를 직접 많이 만들기보다 Executor 계열 API나 가상 스레드 같은 더 높은 수준의 동시성 도구를 사용하는 경우가 많지만, Thread 와 Runnable 의 기본 원리를 이해하면 이후 개념을 익히기 쉽다. 10. join() : 다른 스레드가 끝날 때까지 기다리기 Thread worker = new Thread(() -> { System.out.println("백그라운드 작업"); }); worker.start(); worker.join(); System.out.println("작업 완료 후 실행"); join() 은 대상 스레드가 종료될 때까지 현재 스레드를 기다리게 한다. InterruptedException 처리가 필요할 수 있다. 11. 공유 데이터와 경쟁 상태 여러 스레드가 같은 값을 동시에 수정하면 예상하지 못한 결과가 나올 수 있다. class Counter { int value = 0; void increment() { value++; } } value++ 는 겉보기와 달리 읽기 → 증가 → 쓰기 과정이므로 여러 스레드가 동시에 실행하면 증가가 유실될 수 있다. 12. synchronized 로 임계 구역 보호하기 class Counter { private int value = 0; public synchronized void increment() { value++; } public int getValue() { return value; } } 한 번에 하나의 스레드만 increment() 의 임계 구역에 들어가게 해 경쟁 상태를 줄인다. 블록 단위로 특정 객체를 락으로 사용할 수도 있다. synchronized (lock) { // 공유 자원 접근 } 동기화는 안전성을 높이지만 락 경쟁이 많으면 성능에 영향을 줄 수 있다. 필요한 범위를 작게 잡는 것이 중요하다. 13. Scanner 로 콘솔 입력 받기 import java.util.Scanner; Scanner scanner = new Scanner(System.in); System.out.print("페이지 번호: "); int page = scanner.nextInt(); System.out.println("입력된 페이지: " + page); 대표 메소드는 다음과 같다. next() : 공백 전까지 한 단어 nextInt() : 정수 nextDouble() : 실수 nextLine() : 한 줄 전체 nextInt() 뒤에 바로 nextLine() 을 사용하면 남아 있던 줄바꿈 문자를 읽어 빈 문자열처럼 보일 수 있다. 이 동작은 콘솔 입력을 처음 다룰 때 자주 헷갈린다. 14. print , println , printf System.out.print("A"); System.out.println("B"); System.out.printf("status=%d, path=%s%n", 200, "/api/users"); printf 에서 자주 사용하는 형식 지정자는 다음과 같다. %d : 정수 %f : 실수 %s : 문자열 %n : 플랫폼에 맞는 줄바꿈 System.out.printf("%,d%n", 1234567); // 1,234,567 System.out.printf("%.2f%n", 3.14159); // 3.14 System.out.printf("%04d%n", 12); // 0012 15. 파일과 폴더 다루기 전통적인 File API로 존재 여부와 경로 정보 등을 다룰 수 있다. import java.io.File; File file = new File("app.log"); System.out.println(file.exists()); System.out.println(file.getName()); System.out.println(file.getAbsolutePath()); System.out.println(file.length()); File folder = new File("logs"); folder.mkdir(); 현대 Java에서는 java.nio.file.Path 와 Files API도 많이 사용한다. import java.nio.file.Files; import java.nio.file.Path; Path path = Path.of("logs", "app.log"); Files.createDirectories(path.getParent()); 16. 파일 쓰기와 읽기 쓰기 import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; try (BufferedWriter writer = new BufferedWriter(new FileWriter("app.log"))) { writer.write("server started"); writer.newLine(); writer.write("port=8080"); } catch (IOException e) { System.out.println("파일 쓰기 실패"); } 읽기 import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; try (BufferedReader reader = new BufferedReader(new FileReader("app.log"))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { System.out.println("파일 읽기 실패"); } readLine() 이 더 읽을 내용이 없으면 null 을 반환하므로 while 문으로 파일 끝까지 읽을 수 있다. 핵심 정리 try-catch 로 실행 중 발생 가능한 예외를 처리한다. throw 는 예외를 발생시키고, throws 는 예외를 호출자에게 전달할 수 있음을 선언한다. 닫아야 하는 자원은 try-with-resources 를 사용하면 안전하다. Thread.start() 는 새 스레드에서 run() 을 실행한다. join() 은 다른 스레드가 끝날 때까지 기다린다. 공유 데이터를 여러 스레드가 수정하면 경쟁 상태가 발생할 수 있다. synchronized 는 임계 구역의 동시 접근을 제어한다. Scanner , printf , 파일 API를 이용해 프로그램 외부와 데이터를 주고받을 수 있다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
Java 예외 처리, 스레드, 입출력과 파일 다루기. 문법만 알고 프로그램을 만들면 곧 세 가지 현실적인 문제를 만나게 된다. 예상하지 못한 입력이나 오류가 발생한다. 여러 작업을 동시에 처리해야 한다. 콘솔이나 파일처럼 프로그램 외부와 데이터를 주고받아야 한다. Java에서는 각각 예외 처리 , 스레드 , 입출력 API 로 대응한다. 1. 예외는 프로그램 실행 중 발생하는 문제 상황이다 예를 들어 존재하지 않는 배열 인덱스에 접근하면 예외가 발생한다. int[] values = {10, 20, 30}; System.out.println(values[5]); 프로그램에서 예상 가능한 문제를 처리하려면 try-catch 를 사용한다. try { int[] values = {10, 20, 30};…
Open source