Java 자주발생하는 오류 정리 #2
Frequent Java Cleanup Errors #2
IllegalArgumentException
IllegalArgumentException은 잘못된 인수(argument)가 메서드에 전달되거나 메서드의 인수가 메서드가 지원하지 않는 값 또는 범위일 때 발생하는 예외입니다. 즉, 잘못된 인수로 인해 발생하는 예외입니다.
메서드가 인수의 유효성을 검사하고 인수가 조건을 만족하지 않을 때 발생합니다. 예를 들어, 음수를 입력으로 받지 않아야 하는 메서드에 음수를 전달하거나, 허용하지 않는 문자열을 인수로 받는 메서드에 잘못된 문자열을 전달하는 경우 등이 있습니다.
취약점
- IllegalArgumentException은 프로그램의 불안정성을 야기할 수 있습니다. 악의적인 사용자가 잘못된 인수를 전달하여 프로그램의 동작을 예기치 않게 변경하거나, 비정상적으로 종료시킬 수 있습니다.
오류상황
// 오류예시: 잘못된 인수를 메서드에 전달
public void divide(int dividend, int divisor) {
if (divisor == 0) {
throw new IllegalArgumentException("Divisor cannot be zero.");
}
// 나눗셈 연산 수행
}
솔루션
// 솔루션 1: 메서드에 전달되는 인수를 미리 검사하여 유효성을 확인
public void divide(int dividend, int divisor) {
if (divisor == 0) {
throw new IllegalArgumentException("Divisor cannot be zero.");
}
// 나눗셈 연산 수행
}
// 솔루션 2: try-catch로 예외 처리
public void divide(int dividend, int divisor) {
try {
if (divisor == 0) {
throw new IllegalArgumentException("Divisor cannot be zero.");
}
// 나눗셈 연산 수행
} catch (IllegalArgumentException e) {
// 예외 처리 또는 기본값으로 대체
}
}
솔루션 설명
- 메서드에 전달되는 인수를 미리 검사하여 유효성을 확인합니다. 유효하지 않은 인수가 전달되면 IllegalArgumentException을 발생시켜 예외 처리하거나, 메서드 호출 전에 인수의 유효성을 검사하여 잘못된 인수를 제거하도록 합니다.
- try-catch 블록을 사용하여 IllegalArgumentException이 발생하면 catch 블록에서 해당 예외를 처리합니다. 예외가 발생하면 예외 처리 또는 기본값으로 대체하도록 합니다. 하지만 이 방법은 예외를 잡아서 처리하므로 일반적으로 첫 번째 솔루션보다 덜 선호됩니다.
ClassCastException
ClassCastException은 객체를 캐스트할 때 잘못된 형식으로 캐스트하려고 할 때 발생합니다. 캐스트는 상위 클래스와 하위 클래스 간, 인터페이스와 구현 클래스 간에 가능하지만, 무작위로 임의의 클래스를 캐스트하면 발생하는 예외입니다.
객체를 캐스트할 때 객체의 실제 형식과 캐스트하려는 형식이 맞지 않는 경우에 발생합니다. 예를 들어, Object 클래스를 하위 클래스로 캐스트하려는 경우, 인터페이스를 구현하지 않은 클래스를 인터페이스로 캐스트하려는 경우 등이 있습니다.
취약점
- ClassCastException은 프로그램의 불안정성을 야기할 수 있습니다. 악의적인 사용자가 잘못된 캐스트를 통해 프로그램의 동작을 변경하거나, 예외를 이용하여 시스템을 조작하는 데 사용할 수 있습니다.
오류상황
// 오류예시: 잘못된 캐스트
Object obj = new Integer(10);
String str = (String) obj; // ClassCastException 발생
솔루션
// 솔루션 1: 캐스트하기 전에 형식을 확인하고, instanceof 연산자를 사용하여 적절한 형식으로 캐스트
Object obj = new Integer(10);
if (obj instanceof String) {
String str = (String) obj;
} else {
// 적절한 형식으로 캐스트할 수 없음을 처리
}
// 솔루션 2: try-catch로 예외 처리
Object obj = new Integer(10);
try {
String str = (String) obj; // ClassCastException 발생
} catch (ClassCastException e) {
// 예외 처리 또는 기본값으로 대체
}
솔루션 설명
- 캐스트하기 전에 캐스트할 객체의 형식을 확인하고, instanceof 연산자를 사용하여 적절한 형식으로 캐스트하는지 확인합니다. instanceof 연산자를 사용하여 올바른 캐스트를 수행하거나, 그렇지 않은 경우에는 캐스트할 수 없음을 처리하도록 합니다.
- try-catch 블록을 사용하여 ClassCastException이 발생하면 catch 블록에서 해당 예외를 처리합니다. 예외가 발생하면 예외 처리 또는 기본값으로 대체하도록 합니다. 하지만 이 방법은 예외를 잡아서 처리하므로 일반적으로 첫 번째 솔루션보다 덜 선호됩니다.
UnsupportedOperationException
UnsupportedOperationException은 지원하지 않는 연산을 수행하려고 할 때 발생합니다. 예를 들어, 읽기 전용 컬렉션을 수정하려고 하거나, 지원하지 않는 기능을 사용하려고 할 때 등에 발생하는 예외입니다.
불변(immutable)한 컬렉션을 사용하는데 수정 작업을 수행하려고 할 때, 특정 컬렉션에서 지원하지 않는 기능을 사용하려고 할 때 등에 발생합니다.
취약점
- UnsupportedOperationException은 프로그램의 불안정성을 야기할 수 있습니다. 악의적인 사용자가 지원되지 않는 연산을 이용하여 시스템을 이용하거나 조작하는 데 사용될 수 있습니다.
오류상황
// 오류예시: 읽기 전용 컬렉션을 수정
List<String> readOnlyList = Collections.unmodifiableList(new ArrayList<>());
readOnlyList.add("item"); // UnsupportedOperationException 발생
솔루션
// 솔루션 1: 지원하지 않는 연산을 수행하기 전에 해당 기능을 지원하는지 확인하고, 가능한 경우 대안을 사용
List<String> readOnlyList = Collections.unmodifiableList(new ArrayList<>());
if (readOnlyList instanceof RandomAccess) {
// 지원하는 경우에만 수정 작업 수행
// 또는 다른 수정 가능한 컬렉션을 사용
} else {
// 수정 불가능한 컬렉션을 사용하도록 안내
}
// 솔루션 2: try-catch로 예외 처리
List<String> readOnlyList = Collections.unmodifiableList(new ArrayList<>());
try {
readOnlyList.add("item"); // UnsupportedOperationException 발생
} catch (UnsupportedOperationException e) {
// 예외 처리 또는 기본값으로 대체
}
솔루션 설명
- 지원하지 않는 연산을 수행하기 전에 해당 기능을 지원하는지 확인하고, 가능한 경우 대안을 사용하도록 합니다. RandomAccess 인터페이스를 사용하여 수정 작업을 지원하는 컬렉션인지 확인하거나, 수정 불가능한 컬렉션을 사용하도록 안내합니다.
- try-catch 블록을 사용하여 UnsupportedOperationException이 발생하면 catch 블록에서 해당 예외를 처리합니다. 예외가 발생하면 예외 처리 또는 기본값으로 대체하도록 합니다. 하지만 이 방법은 예외를 잡아서 처리하므로 일반적으로 첫 번째 솔루션보다 덜 선호됩니다.