본문 바로가기

학원/복기

0413 - 정적 내부 클래스,익명의 내부 클래스, 패키지, import 키워드, 어노테이션, 접근 제한자,예외처리

• 정적 내부 클래스(Static InnerClass)

-static 제한자를 사용하여 클래스를 선언한다.

-일반클래스에선 static 제한자 사용해 클래스 선언이 불가능하고, 내부 클래스에서만 가능하다.

-정적 내부클래스에서는 static 제한자를 사용하여 필드 또는 메소드 선언이 가능하다.

 

package nested;

public class OuterTwo {
	private int outerNum;
	
	public OuterTwo() {
		// TODO Auto-generated constructor stub
	}

	public OuterTwo(int outerNum) {
		super();
		this.outerNum = outerNum;
	}

	public int getOuterNum() {
		return outerNum;
	}

	public void setOuterNum(int outerNum) {
		this.outerNum = outerNum;
	}
	
	public void outerDisplay() {
		System.out.println("outerNum = " + outerNum);
		
	}

	//정적 내부 클래스(Static InnerClass) 
	public static class InnerTwo  {
		private int innerNum;
		private static int staticNum = 300;
		
		public InnerTwo() {
			// TODO Auto-generated constructor stub
		}

		public InnerTwo(int innerNum) {
			super();
			this.innerNum = innerNum;
		}

		public int getInnerNum() {
			return innerNum;
		}

		public void setInnerNum(int innerNum) {
			this.innerNum = innerNum;
		}

		public static int getStaticNum() {
			return staticNum;
		}

		public static void setStaticNum(int staticNum) {
			InnerTwo.staticNum = staticNum;
		}
		
		public void innerDisplay() {
			System.out.println("innerNum = " + innerNum);
			System.out.println("staticNum = " + staticNum);				
		} 
	}
}



//출력
package nested;

import nested.OuterTwo.InnerTwo;

public class OuterTwoApp {
	public static void main(String[] args) {
		OuterTwo outerTwo = new OuterTwo();
		outerTwo.outerDisplay(); //outerNum = 0
		
		
		//정적 내부클래스의 생성자를 직접 호출하여 객체 생성 가능 
		InnerTwo innerTwo = new InnerTwo(200); 
		innerTwo.innerDisplay(); 
        
        //innerNum = 200
		 //staticNum = 300
		
		
	}
}

 

외부클래스정적 내부클래스로  객체를 생성하여 접근제한자에 상관없이 정적 내부클래스 필드 또는 메소드 참조 가능

public void outerDisplay() {
		InnerTwo innerTwo = new InnerTwo(200);
		System.out.println("innerNum = " + innerTwo.innerNum);
		innerTwo.innerDisplay();
	}

 

외부클래스에서는 정적 내부클래스를 사용하여 정적필드 또는 정적메소드 접근 가능 

 

public void outerDisplay() {
		System.out.println("staticNum = " + InnerTwo.staticNum);
	}

 

정적 내부클래스에서는 외부클래스의 필드 또는 메소드 참조 불가능  => 외부클래스의 정적필드 또는 정적메소드는 참조 가능 

 

public void innerDisplay() {
			//System.out.println("outerNum = " + outerNum);
			//outerDisplay();		
		}

•  지역클래스(LocalClass) 

메소드 내부에 선언된 클래스 - 메소드가 종료되면 자동 소멸 


- 지역클래스에 final 또는 abstract 제한자만 사용하여 선언이 가능하다 
- 접근제한자 및 static 제한자를 사용하여 지역클래스를 선언할 경우 에러 발생  (필드, 메소드도 마찬가지로 에러 발생)
- 지역클래스는 비동기식 처리를 위한 스레드 객체를 생성하기 위해 사용한다. 

 

 

package nested;

public class OuterThree {
	private int outerNum;
	
	public OuterThree() {
		// TODO Auto-generated constructor stub
	}

	public OuterThree(int outerNum) {
		super();
		this.outerNum = outerNum;
	}

	public int getOuterNum() {
		return outerNum;
	}

	public void setOuterNum(int outerNum) {
		this.outerNum = outerNum;
	}
	
	public void outerDisplay() {
		System.out.println("outerNum = " + outerNum);
		
		//외부클래스에서는 지역클래스 사용 불가능
	}
	
	public void local() {
		//지역클래스(LocalClass)
		class InnerThree {
			int innerNum;
			
			void innerDisplay() {
				System.out.println("innerNum = " + innerNum);
			}
		}
		
		//지역클래스가 선언된 메소드에서만 객체를 생성하여 필드 또는 메소드 참조가 가능하다 
		InnerThree innerThree = new InnerThree();
		innerThree.innerNum = 200;
		innerThree.innerDisplay();
	}
}

//출력 

package nested;

public class OuterThreeApp {
	public static void main(String[] args) {
		OuterThree outerThree = new OuterThree(100);
		
		outerThree.outerDisplay(); //outerNum = 100
		outerThree.local(); //innerNum = 200
	} 
}

 


 

인터페이스를 사용하여 참조변수는 생성가능하지만 객체 생성은 불가능하다. 이는 인터페이스가 클래스가 상속받기 위한 자료형으로 쓰이기 때문이다. 인터페이스를 상속받은 자식클래스는 인터페이스에 선언된 모든 추상메소드를 반드시 오버라이드 선언 해주어야 한다. 따라서, 인터페이스를 상속받은 자식클래스로 객체를 생성하여 인터페이스로 생성된 참조변수에 저장이 가능하다. 인터페이스를 상속받은 이름이 없는 자식클래스를 선언하고 인터페이스의 메소드를 오버라이드 선언하여 객체 생성이 가능하다. -> 익명의 내부 클래스(지역클래스)

 

•  익명의 내부 클래스 (Anonymous InnerClass)

: 인터페이스 또는 추상클래스를 상속받은 이름이 없는 자식클래스 -> 익명의 내부클래스로 하나의 객체를 생성할 목적으로 사용 
  -익명의 내부클래스는 상속받은 인터페이스 또는 추상클래스의 모든 추상메소드를 모두 오버라이드 선언해줘야 한다.

 

//Anonymous 인터페이스 선언 
package nested;

public interface Anonymous {
	void display();
	
}

//출력
package nested;

public class AnonymousApp {
	public static void main(String[] args) {
		//인터페이스 사용하여 참조변수는 생성가능하지만 객체 생성은 불가능
		//Anonymous anonymous = new Anonymous(); >> 에러 
		
		//인터페이스를 상속받은 이름이 없는 자식클래스를 선언하고 인터페이스의 메소드를
		//오버라이드 선언하여 객체 생성 가능 - 익명의 내부 클래스(지역클래스)
		Anonymous anonymous = new Anonymous() {
			
			@Override
			public void display() {
				System.out.println("익명의 내부클래스의 오버라이드 메소드 호출");
			}
		};
		
		anonymous.display();
	}
}

 

객체를 하나만 만들고 싶을때는 굳이 지역클래스를 만들 필요 없이, 익명의 내부 클래스 이용해 객체 생성할 목적으로 사용한다.
이클립스 자동 생성 : [ctrl] + [space] >> Annonymous InnerType >> 엔터  

 


•  패키지(Package) 

같은 목적의 자료형(참조형)을 명확하게 구분하여 그룹화 하기 위해 사용 (폴더와 유사)

 -> Java 참조형 : 클래스(Class), 인터페이스(Interface), 열거형(Enum)

-Java 자료형을 보다 쉽게 관리하기 위해 패키지를 사용한다.
-패키지의 이름은 도메인을 역방향으로 나열하고 그룹명을 지정하여 작성하는 것을 권장한다. 
-도메인(Domain) : 인터넷에서 개인 또는 그룹이 사용하기 위한 네트워크 식별자 

 ex) itwill.xyz : 도메인 >> xyz.itwill.board (게시판에 관련된..)


-패키지에 작성된 소스파일의 처음 위치에는 소스파일이 작성된 패키지를 반드시 명확하게 작성

형식) package 패키지경로;

 

=> Java 자료형이 어떤 패키지에서 선언된 자료형인지를 명확하게 구분하여 사용할 수 있다 

 

 

같은 이름의 클래스와 인터페이스들이 상당히 많은데, 이를 구분해줄 수 있는 것이 패키지이다. 클래스의 이름이 같다 해서 같은 클래스가 아니다. 패키지가 다르다는 것은 만들어준 그룹 자체가 다르다는 뜻이다. 패키지명을 이용하면 클래스 관리가 수월해진다.


기본적으로, 다른 패키지의 클래스에는 접근할 수 없다.
같은 패키지에 작성된 클래스는 패키지 경로 표현 없이 클래스 접근이 가능하다  

형식) 클래스명


하지만 다른 패키지에 작성된 클래스는 반드시 경로를 표현해야만 클래스 접근이 가능하다.  

형식) 패키지경로.클래스명


따라서 import 기능을 사용해주어야 한다.

 

 import 키워드

: 다른 패키지에 작성된 Java 자료형을 명확히 표현하여 접근하기 위한 키워드 

형식) import 패키지경로.자료형 //>> 자료형 대신 *(전체) 사용이 가능하다


- package 키워드로 작성된 명령 하단에 선언하며 자료형 위에 선언


- 이클립스에서는 다른 패키지에서 작성된 자료형을 사용할 경우 import 명령을 자동 완성하는 기능을 제공한다

[Ctrl]+[Space] //=> 같은 이름의 자료형이 여러개인 경우 선택


- import 명령을 정리하는 단축키 : 불필요한 자료형에 대한 import 설정을 제거하거나 필요한 자료형에 대한 import 설정을 추가하는 기능을 제공한다.

 [Ctrl]+[Shift]+[O]

 

import 예시)

 

//xyz.itwill.subject 패키지에 JavaSbject, OracleSubject 클래스 선언
package xyz.itwill.subject;

public class JavaSubject {
	public void display() {
		System.out.println("아이티윌 학원의 Java 과정입니다.");
	}
}

package xyz.itwill.subject;

public class OracleSubject {
	public void display() {
		System.out.println("아이티윌 학원의 Oracle 과정입니다.");
	}
}

//xyz.uniwill.subject 패키지에 JavaSubject 클래스 선언 
package xyz.uniwill.subject;

public class JavaSubject {
	public void display() {
		System.out.println("유니윌 학원의 Java 과정입니다.");
	}
}

 

xyz.itwill.app 패키지에서 다른 패키지에서 작성된 클래스들에 접근하기

 

package xyz.itwill.app;

//package 키워드로 작성된 명령 하단에 선언하며 자료형 위에 선언
import xyz.itwill.subject.OracleSubject;
import xyz.itwill.subject.JavaSubject;


//자료형의 이름이 같은 경우 import 처리 불가능 
//import xyz.uniwill.subject.JavaSubject;

public class SubjectApp {
	public static void main(String[] args) {

		//다른 패키지에 작성된 클래스는 반드시 패키지 경로를 표현해야만 클래스 접근 가능
		//xyz.itwill.subject.OracleSubject subject1 = new xyz.itwill.subject.OracleSubject();
		
		//다른 패키지에 작성된 클래스는 import 처리한 경우 패키지 경로 표현없이 클래스 접근 가능
		OracleSubject subject1 = new OracleSubject();
		subject1.display(); //아이티윌 학원의 Oracle 과정입니다.
		
		JavaSubject subject2 = new JavaSubject();
		subject2.display(); //아이티윌 학원의 Java 과정입니다.
		
		//import 설정이 불가능한 자료형은 패키지 경로를 반드시 표현해야만 접근 가능  
		xyz.uniwill.subject.JavaSubject subject3 = new xyz.uniwill.subject.JavaSubject();
		subject3.display(); //유니윌 학원의 Java 과정입니다.
	}
}

 


• Date 클래스

 : 날짜와 시간을 저장하기 위한 클래스 (-> java.util / java.sql  두 종류 중 java.util.Date 클래스 import)
→ Date 클래스의 기본 생성자를 사용하여 객체를 생성하면 시스템(운영체제-window,mac...)의 현재 날짜와 시간이 저장된 Date 객체가 생성된다.

- Date.getYear() : Date 객체에 저장된 날짜와 시간에서 년도를 정수값으로 반환하는 메소드
→ 1990년을 기준으로 1년에 1씩 증가된 년도값이 반환된다 
→ @Deprecated 어노테이션이 적용된 메소드 

• @Deprecated 어노테이션 

메소드 사용을 권장하지 않도록 설정하는 어노테이션 
→ @Deprecated 어노테이션이 적용된 메소드를 호출할 경우 경고가 발생된다.

경고를 없애고 싶으면, 해당 메소드에 마우스를 갖다대고 @SuppressWarnings 어노테이션을 사용하면 된다


• @SuppressWarnings 어노테이션 

경고 메시지를 제거하는 어노테이션 
→ value 속성을 사용하여 경고 관련 속성값을 설정 
→ value 속성외에 다른 속성이 없는 경우 속성값만 설정 가능 

 @SuppressWarnings(value = "deprecation")  
 @SuppressWarnings("deprecation")

 

-자바에서 알아야할 어노테이션 : @Override @Deprecated @SuppressWarnings

 

 

예시) 키보드로 이름과 태어난 년도를 입력받아 나이를 계산하여 이름과 나이를 출력하는 프로그램 작성

package xyz.itwill.app;

import java.util.Date;
import java.util.Scanner;

//키보드로 이름과 태어난 년도를 입력받아 나이를 계산하여 이름과 나이를 출력하는 프로그램 작성
//ex) 이름 입력 >> 홍길동
//	  태어난 년도 >> 2000
//    [결과]홍길동님의 나이는 24살입니다. 
public class CalcAgeApp {
	public static void main(String[] args) {
		//Scanner 클래스로 객체를 생성하여 참조변수에 저장 
		Scanner scanner = new Scanner(System.in);
		
		//키보드를 이용하여 사용자로부터 이름과 태어난 년도를 입력받아 변수에 저장
		System.out.print("이름 입력 >> ");
		String name = scanner.nextLine(); //키보드에 입력된 값을 문자열로 반환해 name 변수에 저장
		
		System.out.print("태어난 년도 >> ");
		int birthYear = scanner.nextInt(); //키보드에 입력된 값을 정수값으로 반환해 birthYear 변수에 저장
		
		//java.util.Date 클래스로 객체를 생성하여 참조변수에 저장 

		Date now = new Date();
		
		@SuppressWarnings("deprecation")
		int currentYear = now.getYear() + 1900; //1900년이 기준이기때문에 실제 년도를 구하려면 1900을 더해야함
		
		//현재 년도와 태어난 년도를 이용하여 나이 계산
		//int age = 2023 - birthYear + 1; 
		int age = currentYear - birthYear + 1; 
		
		System.out.println("[결과]" + name + "님의 나이는 " + age + "살입니다." );
		
		scanner.close();	
	}
}

 


* 접근 제한자 (Access Modifier)

: 클래스, 필드, 메소드에 대한 접근 설정을 위한 키워드 

종류) private, package(default), protected, public
// private(가장 제한적) >> package >> protected >> public

 private 접근 제한자 

: 클래스 내부에서만 접근 가능하며 클래스 외부에서는 접근 불가능 - '은닉화' 하는 제한자

 

같은 패키지 내부에서도 접근 불가능  

package xyz.itwill.access;

//private 접근 제한자
public class PrivateMember {
	private int num;
	
	@SuppressWarnings("unused") //경고 없애주는 @SuppressWarnings 어노테이션 
	private void display() {
		System.out.println("num = " + num);
	}
}

//같은 패키지, 다른 클래스
package xyz.itwill.access;

public class PrivateMemberUse {
	public void run() {
		PrivateMember member = new PrivateMember();
		
		//private 접근제한자로 설정된 필드와 메소드에 접근할 경우 에러 발생 
		//member.num = 100;
		//member.display();
	}
}

 

• public 접근 제한자 

모든 패키지의 클래스에서 접근 가능하도록 설정 

-public 클래스 : public 접근 제한자를 사용하여 클래스 선언 
→ public 클래스로 설정된 클래스는 모든 패키지의 클래스에서 접근 가능  
→ public 클래스로 설정되지 않은 클래스는 다른 패키지의 클래스에서 접근 불가능 
→ 하나의 소스파일에는 public class를 하나만 설정 가능

 

public이 아닌 일반 class는 여러개 설정 가능하지만, 하나의 소스파일 안에 클래스를 여러개 만들어 주는 것은 권장하진 않는다. 
하나의 소스파일엔 하나의 클래스만 만들어 주는것을 권장한다. 
(만약 하나의 소스파일에 여러 클래스가 존재할 경우, 파일명은 public class로 해주고, public class가 아닌 일반 class로만 구성된 경우, 파일명은 아무거나 지정해줘도 상관 없다.)

 

//동일한 패키지

package xyz.itwill.access;

//public 클래스
public class PublicMember {
	public int num;
	
	public void display() {
		System.out.println("num = " + num);
	}
}


package xyz.itwill.access;

//같은 패키지 내부 다른 클래스에 접근 가능 
public class PublicMemberUse {
	public void run() {
		PublicMember member = new PublicMember();
		
		member.num = 100;
		member.display();
	}
}


//다른 패키지
//public은 모든 패키지의 클래스에서 접근 가능하기 때문에, 에러나지 않는다
package xyz.itwill.other;

//PublicMember 클래스를 가져다 쓰기 위해서는 import 해주어야 함 
import xyz.itwill.access.PublicMember;

public class PublicMemberOtherUse {
	public void run() {
		PublicMember member = new PublicMember();
		
		member.num = 100;
		member.display();
	}
}

 

• package 접근 제한자 

같은 패키지의 클래스에서 접근 가능하도록 설정
→  다른 패키지의 클래스에서 무조건 접근 불가능
→  클래스, 필드, 메소드 선언시 접근 제한자 관련 키워드를 사용하지 않으면 자동 설정되는 접근 제한자 (키워드가 따로 존재하지 않음)

 

package xyz.itwill.access;

//package 접근 제한자 
public class PackageMember {
	int num;
    
	void display() {
		System.out.println("num = " + num);
	}
	
}

//같은 패키지
package xyz.itwill.access;

public class PackageMemberUse {
	public void run() {
		PackageMember member = new PackageMember();
		
		member.num = 100;
		member.display();
	}
}


//다른 패키지 >> 에러발생
package xyz.itwill.other;

import xyz.itwill.access.PackageMember;

public class PackageMemberOtherUse {
	public void run() {
		@SuppressWarnings("unused")
		PackageMember member = new PackageMember();
		
		//member.num = 100;
		//member.display();
	}
}

//다른 패키지 >> 에러 발생 
package xyz.itwill.other;

import xyz.itwill.access.PackageMember;

//상속 받아도 에러 발생 
public class PackageMemberOtherInheritanceUse extends PackageMember {
	public void run() {
		//num = 100;
		//display();
	}
}

 

 

• protected 접근 제한자 

: 같은 패키지의 클래스에서 접근 가능하도록 설정

→  다른 패키지의 클래스에서 접근 불가능
→  다른 패키지의 클래스에서 protected 접근 제한자의 필드 또는 메소드의 클래스를 상속을 받은 경우 접근 가능 
package와의 차이점 : package는 무조건 접근 불가능

 

package xyz.itwill.access;

public class ProtectedMember {
	protected int num;
	
	protected void display() {
		System.out.println("num = " + num);
	}
}

//같은 패키지의 클래스에서 접근 가능 
package xyz.itwill.access;

public class ProtectedMemberUse {
	public void run() {
		ProtectedMember member = new ProtectedMember();
		
		member.num = 100;
		member.display();
	}
}


//다른 패키지의 클래스에서 접근 불가능
package xyz.itwill.other;

import xyz.itwill.access.ProtectedMember;

public class ProtectedMemberOtherUse {
	public void run() {
		@SuppressWarnings("unused")
		ProtectedMember member = new ProtectedMember();
		
		//member.num = 100;
		//member.display();
	}
}


//protected는 다른 패키지에서 상속을 받으면 접근 가능
package xyz.itwill.other;

import xyz.itwill.access.ProtectedMember;

public class ProtectedMemberOtherInheritanceUse extends ProtectedMember{
	public void run() {
		num = 100;
		display();
	}
}

 


• 예외(Exception) 

: 사용자에 의해 프로그램이 잘못 실행되거나 프로그램이 잘못 개발되어 실행될 경우 발생되는 프로그램 오류 
→  프로그램 실행시 예외가 발생되면 예외가 발생된 지점에서 프로그램이 강제 종료된다.
→  예외가 발생되어 프로그램이 강제로 종료되는 것을 방지하거나 프로그램이 강제로 종료된 이유를 알기 위해 예외처리(ExceptionHandle) 

- Java에서는 예외를 처리하기 위해 다양한 예외클래스를 제공한다.

- 예외클래스(ExceptionClass) : 예외 관련 정보를 저장하기 위한 클래스   Exception 클래스를 상속받아 작성된 자식클래스
(API 문서 >> java.base >> java.lang >> Exceptions 에서 예외클래스들을 확인할 수 있다.)
→  프로그램 실행시 예외가 발생되면 JVM은 해당 예외에 대한 예외클래스로 객체를 생성하여 제공한다. 

- Throwable 클래스 : 프로그램에서 발생되는 모든 오류정보를 저장하기 위한 부모 클래스 
   → Throwable 클래스의 자식클래스 : Error 클래스, Exception 클래스

   → 일반적으로 Exception 클래스로 예외처리 한다.


• 예외의 종류

1.일반 예외 : 프로그램 실행시 예외가 발생될 가능성이 높아 예외처리 하지 않은 경우 컴파일시 에러가 발생된다. 
  RuntimeException 클래스를 상속받지 않은 클래스로 예외처리 

2.실행 예외 : 프로그램 실행시 예외가 발생될 가능성이 낮아 예외처리를 하지 않아도 컴파일시 에러가 발생하지 않는다.
 (실행 예외도 예외가 발생될 가능성이 아예 없는 것이 아니라, 가능성이 낮은 것이기 때문에 예외처리 해주는 것이 좋다.) 
 RuntimeException 클래스를 상속받은 클래스로 예외처리 
→ 실행 예외는 예외처리를 하지 않은 경우 JVM이 자동으로 예외처리하여 예외메세지 제공 

 

• 예외처리 방법 

: try ~ catch 구문 사용 

형식) try {
	예외가 발생될 수 있는 명령;
		...
     } catch(예외클래스 참조변수) {
	   예외처리명령;
		...
     } finally {
	 예외 발생과 상관없이 무조건 실행될 명령;     //finally는 써도 되고 안써도 된다. 거의 쓰지 않음 
		...
     }

 

→ try 키워드로 생성된 블럭의 명령에서 실행할 때 예외가 발생될 경우 JVM이 해당 예외에 대한  예외클래스로 객체를 생성 
 try 키워드로 생선된 블럭에서 발생된 예외 관련 객체를 catch 키워드로 설정된 블럭으로 전달하여 참조변수에 저장 
    - 참조변수에 저장된 예외 관련 객체의 메소드를 호출하여 예외 처리 
→ try 키워드로 생성된 블럭에서 예외가 발생되면 프로그램이 종료되지 않고 catch 키워드의 블럭으로 프로그램의 흐름(스레드)이 이동하여 예외처리 명령 실행 
 catch 키워드로 블럭을 여러개 작성 가능 - 다양한 예외를 구분하여 예외처리 가능 

 

finally 키워드의 블럭에는 예외 발생과 상관없이 무조건 실행될 명령 작성 - 생략 가능  -> 사용 자원에 대한 제거 명령 실행 

 

예외처리 예시)

public class ExceptionHandleApp {
	public static void main(String[] args) {
		int[] array = {10,20,30,40,50};
		
		try{ 
			//배열 요소의 첨자가 사용범위를 벗어난 경우 ArrayIndexOutOfBoundsException 발생 
			for(int i = 0 ; i <= array.length ; i++) {
				System.out.println("array[" + i + "] = " + array[i]); //예외발생 - 예외객체 생성
			} 
			System.out.println("[메시지]프로그램이 정상적으로 실행되었습니다.");
		} catch (ArrayIndexOutOfBoundsException e) { //예외객체를 전달받아 참조변수에 저장
			//프로그램 사용자에게 예외 관련 메시지 출력 => 선택 
			//System.out.println("[에러]프로그램에 예기치 못한 오류가 발생되었습니다.");
			
			//프로그램 개발자에게 예외 관련 메시지를 기록하여 제공 - 에러 로그 => 필수 
			// => 참조변수에 저장된 예외 관련 객체 메소드를 호출하여 작성
			//Throwable.getMessage() : 예외 객체에 저장된 예외 메세지를 반환하는 메소드 
			//System.out.println("[예외]" + e.getMessage()); //원래는 출력하는 것이 아니라 로그파일에 저장해야한다.
				
			//Throwable.printStackTrace() : 예외가 발생된 경로를 역추적하여 발생된 정보를 
			//제공받아 출력하는 메소드 
			e.printStackTrace(); //로그파일에 저장할 땐 getStackTrace() 사용 
		} finally {
			System.out.println("[메시지]예외 발생과 상관없이 무조건 실행될 명령");
		}
		
		
		
	}
}

 

/* 출력결과

array[0] = 10
array[1] = 20
array[2] = 30
array[3] = 40
array[4] = 50
java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 5
	at java_03/xyz.itwill.exception.ExceptionHandleApp.main(ExceptionHandleApp.java:9)
[메시지]예외 발생과 상관없이 무조건 실행될 명령

*/