프로그램 개발은 복잡하고 다양한 도전을 수반하며, 종종 다양한 에러와 마주합니다. 이 블로그 글에서는 자주 발생하는 프로그래밍 에러에 대해 정의하고, 각 에러에 대한 해결 방법을 자세하게 설명하겠습니다. 개발자들이 실제로 마주치게 되는 상황에 대비하여, 문제를 신속하게 해결할 수 있는 방법을 제시합니다.
1. NullPointerException :
에러 정의:
프로그램이 null 값을 참조할 때 발생하는 예외로, 변수나 객체가 초기화되지 않았거나 적절한 값으로 설정되지 않았을 때 발생합니다.
해결 방법:
- 코드에서 null 체크: null 값을 참조하기 전에 항상 null 여부를 체크하여 안전하게 참조하도록 합니다.
if (myObject != null) { // null이 아닌 경우에만 접근 myObject.doSomething(); }
- 객체 초기화: 객체를 생성하고 초기화할 때, null이 아닌 기본값이나 유효한 값을 할당합니다.
MyClass myObject = new MyClass(); // 또는 유효한 값으로 초기화
예시:
public class Example {
public static void main(String[] args) {
String myString = null;
// 예시 1: null 체크
if (myString != null) {
System.out.println(myString.length());
}
// 예시 2: 객체 초기화
String anotherString = "Hello, World!";
}
}
2. ArrayIndexOutOfBoundsException :
에러 정의:
배열의 길이를 벗어난 인덱스로 접근할 때 발생하는 예외입니다.
해결 방법:
- 인덱스 범위 확인: 배열의 인덱스가 배열의 길이를 초과하지 않도록 합니다.
for (int i = 0; i < array.length; i++) { // 배열의 길이를 초과하지 않도록 조건 확인 System.out.println(array[i]); }
- 배열 길이 동적 확인: 배열의 길이가 동적으로 변하는 경우, 동적으로 길이를 확인하여 예외를 방지합니다.
if (index < array.length) { // 배열의 길이를 초과하지 않도록 조건 확인 System.out.println(array[index]); }
예시:
public class Example {
public static void main(String[] args) {
int[] myArray = {1, 2, 3};
// 예시 1: 인덱스 범위 확인
for (int i = 0; i < myArray.length; i++) {
System.out.println(myArray[i]);
}
// 예시 2: 배열 길이 동적 확인
int index = 5;
if (index < myArray.length) {
System.out.println(myArray[index]);
}
}
}
3. FileNotFoundException :
에러 정의:
파일을 찾을 수 없는 경로에 대한 파일 조작 작업을 수행하려고 할 때 발생하는 예외입니다.
해결 방법:
- 파일 존재 여부 확인: 파일이 실제로 존재하는지 여부를 확인합니다.
File file = new File("path/to/file.txt"); if (file.exists()) { // 파일이 존재하는 경우에만 작업 수행 // ... }
- 예외 처리: 파일을 열거나 조작하는 코드에 대한 예외 처리를 추가하여 예외가 발생할 경우 프로그램이 비정상적으로 종료되지 않도록 합니다.
try { // 파일 조작 작업 수행 // ... } catch (FileNotFoundException e) { // 파일을 찾을 수 없는 예외 처리 e.printStackTrace(); }
예시:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Example {
public static void main(String[] args) {
// 예시: 파일 존재 여부 확인
File file = new File("path/to/file.txt");
if (file.exists()) {
// 파일이 존재하는 경우에만 작업 수행
try {
// 예시: 파일 조작 작업
Scanner scanner = new Scanner(file);
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close();
} catch (FileNotFoundException e) {
// 파일을 찾을 수 없는 예외 처리
e.printStackTrace();
}
}
}
}
4. SQLException :
에러 정의:
데이터베이스와 관련된 작업 중 SQL 쿼리 실행에 문제가 발생할 때 발생하는 예외입니다.
해결 방법:
- 쿼리 검토: 실행하려는 SQL 쿼리를 정확히 검토하고, 문법 오류 또는 잘못된 쿼리를 수정합니다.
String sqlQuery = "SELECT * FROM myTable WHERE condition"; try { // 쿼리 실행 // ... } catch (SQLException e) { // SQL 예외 처리 e.printStackTrace(); }
- 프리페어드 스테이먼트 사용: 프리페어드 스테이먼트를 사용하여 SQL 인젝션을 방지하고 쿼리를 미리 컴파일하여 실행합니다.
String sqlQuery = "SELECT * FROM myTable WHERE id = ?"; try { PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery); preparedStatement.setInt(1, myId); ResultSet resultSet = preparedStatement.executeQuery(); // 결과 처리 // ... } catch (SQLException e) { // SQL 예외 처리 e.printStackTrace(); }
예시:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Example {
public static void main(String[] args) {
// 예시: 쿼리 검토 및 프리페어드 스테이먼트 사용
String sqlQuery = "SELECT * FROM myTable WHERE id = ?";
try {
// 연결 설정
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
// 쿼리 실행
PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);
preparedStatement.setInt(1, 123);
ResultSet resultSet = preparedStatement.executeQuery();
// 결과 처리
while (resultSet.next()) {
System.out.println(resultSet.getString("columnName"));
}
// 연결 닫기
connection.close();
} catch (SQLException e) {
// SQL 예외 처리
e.printStackTrace();
}
}
}
5. ConcurrentModificationException :
에러 정의:
컬렉션을 반복하면서 동시에 수정을 시도할 때 발생하는 예외입니다.
해결 방법:
- 반복 도중 수정을 피하기: 컬렉션을 반복하면서 수정이 필요한 경우, 수정 대신 해당 요소를 저장하여 반복이 완료된 후 수정을 수행합니다.
List<String> myList = new ArrayList<>(); Iterator<String> iterator = myList.iterator(); while (iterator.hasNext()) { String element = iterator.next(); // 수정 대신 요소를 저장 // ... }
- 동기화 사용: 동기화된 블록을 사용하여 여러 스레드 간의 안전한 수정을 보장합니다.
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>()); synchronized (synchronizedList) { // 안전한 수정 작업 // ... }
예시:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class Example {
public static void main(String[] args) {
// 예시: 반복 도중 수정을 피하기
List<String> myList = new ArrayList<>();
Iterator<String> iterator = myList.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
// 수정 대신 요소를 저장
// ...
}
// 예시: 동기화 사용
List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
synchronized (synchronizedList) {
// 안전한 수정 작업
// ...
}
}
}
6. ClassCastException :
에러 정의:
부적절한 형변환을 시도할 때 발생하는 예외로, 상위 클래스를 하위 클래스로 형변환하려 할 때나 클래스 간의 호환되지 않는 형변환 시도 시 발생합니다.
해결 방법:
- 인스턴스의 실제 타입 확인: instanceof 연산자를 사용하여 형변환 전에 인스턴스의 실제 타입을 확인합니다.
if (myObject instanceof MyType) { // 형변환을 시도하기 전에 확인 MyType myTypeObject = (MyType) myObject; // ... }
- 캐스팅 전에 타입 확인: 형변환 전에 명시적으로 타입을 확인하여 안전하게 캐스팅합니다.
if (myObject.getClass() == MyType.class) { // 캐스팅 전에 타입 확인 MyType myTypeObject = (MyType) myObject; // ... }
예시:
public class Example {
public static void main(String[] args) {
// 예시: 인스턴스의 실제 타입 확인
Object myObject = "Hello, World!";
if (myObject instanceof String) {
String myString = (String) myObject;
System.out.println(myString.toUpperCase());
}
// 예시: 캐스팅 전에 타입 확인
Object anotherObject = new Integer(42);
if (anotherObject.getClass() == Integer.class) {
Integer myInteger = (Integer) anotherObject;
System.out.println(myInteger.doubleValue());
}
}
}
7. ArithmeticException :
에러 정의: 0으로 나누거나 모듈로(%) 연산에서 나머지가 0이 되는 경우 발생하는 예외.
해결 방법:
- 조건문 사용: 나누기 전에 0으로 나누는지 여부를 조건문으로 확인합니다.
- 모듈로 연산 조정: 나머지가 0이 되지 않도록 모듈로 연산 시 나누는 값이 0이 아닌지 확인합니다.
예시:
// 에러 발생 전 코드
int result = 10 / 0; // ArithmeticException 발생
// 에러 해결 후 코드
int divisor = 5;
if (divisor != 0) {
int result = 10 / divisor; // 에러 방지
}
8. OutOfMemoryError :
에러 정의: 힙 메모리 공간이 부족하여 객체를 생성할 수 없는 경우 발생하는 에러.
해결 방법:
- 메모리 누수 확인: 불필요한 객체 참조를 해제하고 메모리 누수를 방지합니다.
- JVM 메모리 조절: JVM 옵션을 통해 할당되는 메모리 크기를 조절하여 메모리 부족을 방지합니다.
예시:
// 에러 발생 전 코드 (메모리 누수)
List<Object> list = new ArrayList<>();
while (true) {
list.add(new Object());
}
// 에러 해결 후 코드
List<Object> list = new ArrayList<>();
while (true) {
list.add(new Object());
if (list.size() > 1000) {
list.clear(); // 불필요한 객체 참조 해제
}
}
9. NumberFormatException :
에러 정의: 문자열을 숫자로 변환하려고 할 때, 유효하지 않은 숫자 형식인 경우 발생하는 예외.
해결 방법:
- try-catch 블록 사용: 숫자로 변환 시 예외를 적절히 처리합니다.
- 정규 표현식 검사: 입력값이 숫자 형식에 맞는지 정규 표현식으로 검사합니다.
예시:
// 에러 발생 전 코드
String strNumber = "abc";
int number = Integer.parseInt(strNumber); // NumberFormatException 발생
// 에러 해결 후 코드
String strNumber = "123";
try {
int number = Integer.parseInt(strNumber); // 에러 방지
} catch (NumberFormatException e) {
System.out.println("숫자 형식이 아닙니다.");
}
'About my life > Development Studies' 카테고리의 다른 글
[Algorithm] 초보자를 위한 알고리즘 이해 가이드: 알고리즘의 핵심 (35) | 2023.11.21 |
---|---|
[CS] 컴퓨터 과학 기초: 개발자가 꼭 알아야 하는 CS 지식 (2) | 2023.11.21 |
[개발] 언리얼 엔진을 활용한 간단한 게임 개발 가이드 (0) | 2023.11.21 |
[GAME] 게임 개발 관련 지식 (0) | 2023.08.25 |
[Internet] What is Internet (0) | 2023.06.20 |