배열의 인덱스를 벗어난 접근을 하려고할 때 발생하는 에러이다. 예를 들어 배열 인덱스 0~3까지 4칸짜리 배열이 있는데 4에 접근하려고 하면 발생하는 오류이다.
package TestPackage;
publicclassTest{
publicstaticvoidmain(String[] args){
int index;
int[] arr = {1,2,3,4};
index = 4;
arr[index] = 15;
}
}
/*
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
at TestPackage.Test.main(Test.java:7)
*/
이 예외는 타입 변환을 할 때 발생하는데, 클래스의 경우 부모, 자식 관계가 아니거나 인터페이스의 경우 인터페이스와 구현 클래스 관계가 아닌데 타입 변환을 하려고 할 때 발생하는 예외이다.
package TestPackage;
publicclassTest{
publicstaticvoidmain(String[] args){
Dog dog = new Dog();
changeDog(dog);
Cat cat = new Cat();
changeDog(cat);
}
publicstaticvoidchangeDog(Animal animal){
Dog dog = (Dog) animal; //ClassCastException
}
}
classAnimal{}
classDogextendsAnimal{}
classCatextendsAnimal{}
/*
Exception in thread "main" java.lang.ClassCastException: class TestPackage.Cat cannot be cast to class TestPackage.Dog (TestPackage.Cat and TestPackage.Dog are in unnamed module of loader 'app')
at TestPackage.Test.changeDog(Test.java:11)
at TestPackage.Test.main(Test.java:8)
*/
try 블록에서 작성한 코드가 예외 없이 정상 실행되면 catch 블록은 실행되지 않고, finally 블록이 실행된다.
그러나 try 블록에서 예외가 발생하면 catch 블록이 실행되고 연이어 finally 블록이 실행된다.
예외 발생 여부와 상관없이 finally 블록은 항상 실행된다.
심지어 try 블록과 catch 블록에서 return 문을 사용하더라도 finally 블록은 항상 실행된다.
finally 블록은 옵션으로 생략 가능하다.
package TestPackage;
publicclassTest{
publicstaticvoidmain(String[] args){
System.out.println("정수를 입력하세요");
String input = "10.2";
try { //예외가 발생될 가능성이 있는 코드를 입력int temp = Integer.parseInt(input);//문자열을 정수로 변환
System.out.println("입력된 값 : " + temp);
}
catch(Exception e){ //예외 처리
System.out.println("잘못된 값을 입력했습니다.");
}
finally {
System.out.println("예외가 발생하든 안하든 무조건 실행되는 finally");
}
}
}
/*
정수를 입력하세요
잘못된 값을 입력했습니다.
예외가 발생하든 안하든 무조건 실행되는 finally
*/
try 블록에는 예외 발생 가능 코드가 위치한다.
try 블록의 코드가 예외 발생 없이 정상 실행되면 catch 블록의 코드는 실행되지 않고 finally블록의 코드를 실행한다. 만약 try 블록의 코드에서 예외가 발생하면 실행을 멈추고 catch블록을 실행하여 예외 처리 코드를 실행함. 그 후 finally 블록의 코드를 실행한다.
finally 블록은 생략이 가능하다. 예외 발생 여부와 상관없이 항상 실행할 내용이 있을 경우에만 작성한다. finally 블록은 try블록과 catch 블록에서 return문을 만나더라도 반드시 실행된다.
발생하는 예외의 종류마다 예외 처리를 다르게 하려면 다중 catch 블록을 작성하면 된다.
catch블록이 여러 개라 할지라도 단 하나의 catch 블록만 실행된다. 그 이유는 try 블록에서 동시 다발적으로 예외가 발생하지 않고, 하나의 예외가 발생하면 즉시 실행을 멈추고 해당 catch 블록으로 이동하기 때문이다.
주의해야하는 점 다중 catch 블록을 작성할 때 주의할 점은 상위 예외 클래스가 하위 예외 클래스보다 아래쪽에 위치해야 한다는 것이다.
try 블록에서 예외가 발생했을 때, 예외를 처리해줄 catch 블록은 위에서부터 차례대로 검색된다. 만약 상위(부모) 예외 클래스의 catch블록이 위에 있다면, 하위(자식) 예외 클래스의 catch 블록은 실행되지 않는다.
두 개 이상의 예외를 하나의 catch 블록으로 동일하게 예외를 처리하고 싶을 때에는 catch 블록에 예외 클래스를 기호 |로 연결하면 된다.
publicclassExceptionHandlingExample{
publicstaticvoidmain(String[] args){
String[] array = {"100", "1oo", null, "200"};
for(int i=0; i<=array.length; i++) {
try {
int value = Integer.parseInt(array[i]);
System.out.println("array[" + i + "]: " + value);
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("배열 인덱스가 초과됨: " + e.getMessage());
} catch(NullPointerException | NumberFormatException e) { // 2가지 예외를 동일하게 처리
System.out.println("데이터에 문제가 있음: " + e.getMessage());
}
}
}
}