contents
chapter08
3.내부 클래스
1)내부클래스란?
2)내부 클래스의 종류
3)내부 클래스의 접근성
4)익명 클래스(Anonymous)
chapter09
1)예외(Exception)란?
2.예외처리(Exception Handling)란?
3.try~catch/finally
1)try~catch문
2)finally문
4.객체로서의 예외
5.예외발생 throw
6.예외 던지기(throws)
자바개념정리
-----------------------------------------------------
chapter08
3.내부 클래스
-내부 클래스는 중첩 클래스라고도 부르며 두 클래스 멤버들 간에 서로 쉽게 접근할 수 있도록 만든 것임. 내부 클래스는 외부 Class의 모든 멤버들을 마치 자신의 멤버인 것처럼 사용할 수 있으며 코드의 복잡성을 줄일 수 있음
1)내부클래스란?
-내부 클래스는 어떠한 클래스의 내부에 생성된 클래스임. 클래스가 설계도라면 내부 클래스는 큰 틀의 설계도를 완성하기 위한 내부 부품의 설계도라고 생각하면 됨
-클래스들은 상호작용을 하며 서로의 멤버 변수에 접근함. 이 때 어떠한 클래스의 관계가 긴밀하여 내부에 클래스가 있는 것이 효율적 일 때 내부 클래스를 사용함
class OuterClass{ //외부 클래스 class InnerClass{ //내부 클래스 => 전역변수(접근제어자 satic/instance 정해줘야함) //.... } //... } |
-내부 클래스를 사용하면 추가적으로 코드를 간결하게 만들 수 있음. 하나의 클래스의 내부에 클래스를 감추어 캡슐화할 수 있게 됨
-내부 클래스의 사용은 클래스간의 관계가 긴밀할 때 사용하며 코드가 간결해지는 효과가 있음
2)내부 클래스의 종류
-내부 클래스는 클래스의 내부에 선언되는 클래스이므로 마치 클래스의 멤버 변수와 같이 구별됨. 선언되는 위치에 따라 인스턴스 클래스, 스태틱 클래스, 지역 클래스, 익명 클래스로 구별됨
◎인스턴스 클래스
class OuterClass{ class InnerInstance{ } } |
-외부 클래스에서 멤버 변수의 위치에 선언함. 클래스의 내부에서 인스턴스 멤버처럼 다루어지며 인스턴스 멤버들과 상호작용함
◎스태틱 클래스
class OuterClass{ static class InnerStatic{ } } |
-외부 클래스에서 멤버 변수 위치에 선언함. 클래스의 내부에서 static 멤버처럼 다루어 지며 스태틱 멤버틀과 상호작용함
◎지역 클래스
class OuterClass{ class InnerInstance{ } } |
-메서드의 내부에 지역변수 위치에 선언함. 메서드나 초기화 블록의 내부에서 지역변수 처럼 다루어지며 선언된 영역 내부에서 사용함
3)내부 클래스의 접근성
-내부 클래스도 클래스이기 때문에 선언부에 제어자를 사용함
class OuterClass{ abstract class InnerInstance1{ //... } } |
-그리고 내부 클래스는 멤버변수와 같이 다루어지기 때문에 접근제어자(private, protected)를 사용함
(전연변수, 지역변수)
class OuterClass{ private class InnerInstance1{ //... } protected class InnerInstance2{ //... } } |
-클래스 멤버와 인스턴스 멤버가 서로 호출할 때의 관계와 같이 내부 클래스에도 이와 같은 관계가 있음
<클래스의 종류에 따라 관계를 알아보는 코드>
(1)
package ch08;
class A{ static class StaticInner{} class InstanceInner{} //스태틱 멤버간의 접근 가능 StaticInner st1 = new StaticInner(); //인스턴스 멤버간의 접근 가능 InstanceInner ii1 = new InstanceInner(); static void StaticMethod() { //스태틱 멤버가 스태틱 내부 클래스에 접근 가능 StaticInner st2 = new StaticInner(); //스태틱 멤버는 인스턴스 멤버에 접근 불가 // InstanceInner ii2 = new InstanceInner(); //에러발생 } void InstanceMethod(){ //인스턴스 멤버는 모두 접근 가능 StaticInner st3 = new StaticInner(); InstanceInner ii3 = new InstanceInner(); } } |
-외부 클래스인 A안에 내부 클래스를 선언함. StaticInner 클래스는 스태틱 멤버이고 InstanceInner 클래스는 인스턴스 멤버임
-각각 해당하는 멤버로 클래스를 생성하는 것이므로 당연히 문제가 없음
-스태틱 메서드가 각각의 내부 클래스를 호출하는데 스태틱 멤버가 인스턴스 멤버를 호출하는 것은 가능하지 않으므로 에러가 발생함
-인스턴스 메서드는 스태틱과 인스턴스 클래스 모두 다 접근이 가능함
(2)
package ch08;
class OuterClass { int a = 3; static int b = 4; class Inner { int c = 5; public void innerMethod() { System.out.println("<Inner Class>"); } } static class StaticInner { int d = 6; static int stat = 10; public static void staticMethod() { System.out.println("<Static Inner>"); } } } public class exam58 { public static void main(String[] args) { OuterClass oc = new OuterClass(); System.out.println("OuterClass의 a값=" + oc.a); System.out.println("OuterClass의 b값=" + OuterClass.b); System.out.println("\n===inner클래스 접근하기==="); OuterClass oc2 = new OuterClass(); OuterClass.Inner i = oc2.new Inner(); System.out.println("Inner의 cc값=" + i.c); i.innerMethod(); OuterClass.StaticInner si = new OuterClass.StaticInner(); System.out.println("StaticInner의 d값=" + si.d); si.staticMethod(); OuterClass.StaticInner.staticMethod(); } } |
실행 결과
OuterClass의 a값=3
OuterClass의 b값=4 ===inner클래스 접근하기=== Inner의 cc값=5 <Inner Class> StaticInner의 d값=6 <Static Inner> <Static Inner> |
-Outer 인스턴스를 생성함. 그리고 oc라는 참조변수로 a의 값을 출력함. b는 스태틱 변수이므로 클래스 이름 자체로 접근이 가능함. 내부 클래스에 접근하기 위해서는 먼저 외부 클래스를 생성함. 그리고 생성된 외부 클래스를 통해 내부 클래스를 생성함
OuterClass oc2 = new OuterClass(); |
-이제 내부 클래스의 주소가 참조변수 i에 저장됨. 이제 i를 통해서 내부 클래스의 멤버에 접근함
OuterClass.Inner i = oc2.new Inner(); |
-i에 주소 값이 저장되어있기 때문에 변수에도, 메서드에도 접근이 가능함
System.out.println("Inner의 cc값=" + i.c); i.innerMethod(); |
-스태틱 클래스의 스태틱 매서드는 클래스의 이름만으로도 참조함
OuterClass.StaticInner.staticMethod(); |
4)익명 클래스(Anonymous)
-익명 클래스 또는 무명 클래스는 말 그대로 이름이 없는 클래스임
-익명 클래스는 기존의 클래스를 이용하되 오버라이딩을 하게 됨
Some annoy = new Some() {
private int a = 10; int getter() { return this.a; } void setter(int a) { this = a; } }; //세미콜론 주의 |
-코드를 보면 기존의 클래스 선언 방법과 다른 것을 알 수 있음. 인스턴스를 생성할 때 블록이 있고 그 블록 안에서 클래스의 내용이 새롭게 재정의 된다는 것임. 그렇기 때문에 이 클래스는 'Some'클래스이라고 말할 수 없는 익명 클래스 또는 무명 클래스임. 한 가지 주의할 점은 블록의 마지막에 세미콜론 반드시 붙여야 한다는 것임
package ch08;
class OuterClass1 // a와 b라는 메서드를 가진 클래스 { void a() { System.out.println("method a"); } void b() { } } public class exam59 { public static void main(String[] args) { OuterClass1 o = new OuterClass1() { void a() { // 익명 클래스 안에 있는 메서드는 객체o를 통해서만 가능하다 System.out.println("새롭게 정의한 익명 클래스의 메서드입니다"); } }; // 익명 클래스는 반드시 마지막에 ;를 붙여야 한다. o.a(); // 익명 클래스로 오버라이드한 메서드를 출력 OuterClass1 ok = new OuterClass1(); ok.a(); // 익명 클래스는 일회용이므로 다시 기존의 메서드가 출력 } } |
실행 결과
새롭게 정의한 익명 클래스의 메서드입니다
method a |
-익명 클래스는 인터페이스를 상속받는 데도 사용함. 다만 주의할 점은 인터페이스를 익명 클래스로 사용할 때는 인터페이스 내부의 모든 메서드를 재정의해야 함
chapter09
1)예외(Exception)란?
-예외란 프로그램 실행 중에 발생하는 오류 중에서 처리가 가능한 것을 말함
-프로그램을 작동시킬 때 종종 예기치 못한 상황을 만나가 됨. 이런 상황들은 처음에 프로그램을 만든 프로그래머가 의도한 상황이 아니기 때문에 프로그램 실행 전체에 악영향을 끼칠 수 있음. 이러한 상황 중에서 개발자가 조치할 수 없는 수준의 오류를 에러(Error), 수습될 수 있는 비교적 덜 심각한 오류를 예외(Exception)라고 함
-에러: 개발자가 조치를 취할 수 없는 수준 ex)메모리 부족, JVM 동작이상 -컴파일 에러: 컴파일 시에 발생하는 에러 ex)오타, 잘못된 자료형 등 -런타임 에러: 프로그램이 실행하는 도중에 발생하는 에러 -로직 에러: 실행은 되지만 의도와는 다르게 동작하는 에러 -예외: 다른 방식으로 처리 가능한 오류 ex)입력 값 오류, 네트워크 문제 |
<예외에 대한 간단한 예시 코드>
package ch09;
public class exam60 { public static void main(String[] args) { int a = 0; int b = 2; int c = b/a; //0으로 나눌 수 없어서 예외 발생 } } |
실행 결과
Exception in thread "main" java.lang.ArithmeticException: / by zero //0으로 나눌 수 없음
at ch09.exam60.main(exam60.java:8) |
나눗셈을 하는 코드로 결과 창에 ArithmeticException 에 다른 단어가 보임. 즉 산술적으로 뭔가 문제 발생했다는 것을 알려주고 있음
2.예외처리(Exception Handling)란?
-예외처리란 예외가 발생했을 때 이를 적절히 처리하여 프로그램이 비정상적으로 종료되는 것을 막는 방법임
-예를 들면 사용자가 숫자를 입력해야 하는 곳에 문자를 입력한다거나 컴파일에는 이상이 없지만 개발자가 작성한 알고리즘이 잘못 되어 예외가 발생하는 경우에 개발자가 이러한 예외가 발생할 수도 있다는 것을 미리 인식하고 코드상으로 적절하게 처리를 해 두어 심각한 시스템의 오류를 방지하는 것을 말함
3.try~catch/finally
-try~catch문은 예외를 처리하기 위한 구문임
1)try~catch문
-try문에는 예외가 발생할 수 있는 문장을 넣고 catch문에는 예외가 발생할 경우의 처리 방법을 작성함
try{ //예외 발생할 가능성이 있는 문장들 } catch(예외1){ //예외1에 알맞은 처리 } catch(예외2){ //예외2에 알맞은 처리 } |
-try문으로는 예외가 발생할 가능성이 있는 문장들을 중괄호로 묶어 줌. 그리고 catch문의 소괄호( )에는 발생할 가능성이 있는 예외 클래스의 종류와 참조변수를 적어주고 중괄호 { }안에는 예외가 발생했을 떄 실행해야 할 코드들을 작성함. 만약 발생할 예외의 수가 많다면 복수의 catch문을 사용할 수도 있음
-만약 try문 속에서 예외가 발생했다면 그 예외에 해당하는 catch문을 찾아 문장들을 실행 시킨 다음 try~catch문을 빠져나옴. 하지만 예외가 발생하지 않으면 catch문을 건너 뛰게 됨
package ch09;
public class exam61 { public static void main(String[] args) { int c = 0; try { //감시영역 설정 int[]a= {2, 0}; // 이 안에서 변수생성하면 밖에서 사용못함(따로 선언해야함) int b = 4; c = b/a[2]; //예외발생 System.out.println(c); //예외발생하면 실행안됨(주의: try영역에서 에러가 발생하면 다음 줄의 코드들은 무시되고 catch로 바로 이동함) }catch(ArithmeticException e) { //에러가 발생하면 처리하는 함수 System.out.println("산술 오류 발생"); }catch(ArrayIndexOutOfBoundsException e){ System.out.println("배열 길이 오류 발생"); } System.out.println("예외 처리 공부 중"); System.out.println(c); //try, catch()는 반드시 기본 코드 작성 이후에 적용할 것 } } |
실행 결과
배열 길이 오류 발생
예외 처리 공부 중 0 |
2)finally문
-try~catch문에 선택적으로 finally라는 구문을 추가함. try구문 내부에서 오류가 발생하든 하지 않든 간에 상관없이 무조건 실행되는 구문임
try{ //예외 발생할 가능성이 있는 문장들 } catch(매개변수){ //예외(매개변수)에 알맞은 처리 } finally{ //예외 여부 관계없이 실행되는 부분 } |
-finally는 외부와으 연결을 종료하는 작업에 주로 사용함
try {
System.out.println("외부로 접속"); int c = b/a; System.out.println("연결 해재"); }catch(ArithmeticException e) { System.out.println("오류 발생하였습니다"); System.out.println("연결 해재"); } |
-예를 들어 외부에 접속해서 작업할 경우에 반드시 연결을 해재해야 문제가 발생하지 않음. 위의 코드처럼 작업이 이루어지든 오류가 발생하든 반드시 연결을 해제해야 하는 코드가 실행되어야 할 경우, finally를 사용함
4.객체로서의 예외
-자바에서의 예외는 Exception이라는 클래스 객체임
-객체지향 언어인 자바에서는 예외도 객체로 처리함. 지금까지 예외의 종류로 보았던 ArithmeticException이나 ArrayIndexOutOfBoundsException도 모두 객체임. 따라서 예외 클래스들도 서로 상속의 관계가 있음
-클래스이므로 당연히 Object 클래스를 상속 받음. Object 클래스를 제외한다면 최상위 클래스로는 Throwable 클래스가 있음. 그리고 자식 클래스로 Exception 클래스와 Error클래스가 있고 Exception 클래스를 상속받는 수많은 예외 클래스들이 있음. Exception 클래스가 모든 예외 클래스들의 부모이기 때문에 상속의 개념을 예외처리에 적용시킬 수 있음
◎모든 예외 클래스들을 Exception형의 참조변수로 참조함
try{ //예외 발생할 가능성이 있는 문장들 } catch (Exception e){ //알맞은 처리 } |
-catch문의 소괄호에 특정한 예외가 아니라 예외들의 부모인 Exception 형의 참조변수를 선언해주면 어떤 예외가 발생하더라도 참조함
try{ 예외1발생 //실행 예외2발생 → } catch (Exception e){ → //처리 } |
-이는 부모 클래스 형의 참조변수롤 자식 클래스의 인스턴스를 참조할 수 있는 상속의 특징 때문에 가능한 것임
◎예외 클래스들에서 Exception의 메서드를 사용함
-부모 클래스인 Exception의 메서드를 자식 클래스인 예외 클래스들이 사용함
- Exception의 메서드로는 getMessage( ), toString( ), printStackTrace( ) 등이 있음
try{ //예외 발생할 가능성이 있는 문장들 } catch (Exception e){ //알맞은 처리 } |
5.예외발생 throw
-프로그래머가 고의로 예외를 발생시킬 수도 있음. 예외 클래스의 인스턴스를 생성한 다음 키워드 throw를 이용하면 직접 예외를 발생시킬 수 있음
Exception e = new Exception("Exception"); throw e; //예외 발생 |
package ch09;
public class exam64 { public static void main(String[] args) { try { Exception e = new Exception("고의 예외"); throw e; } catch (Exception e) { System.out.println("예외 발생"); System.out.println(e.getMessage()); } } } |
실행 결과
예외 발생
고의 예외 |
-예외 클래스를 생성해주고 예외를 발생시킴. Exception 클래스 예외가 발생하였으므로 catch문이 실행됨. getMassage 메서드를 통해서 예외 클래스 생성자의 소괄호 안에 작성했던 문장을 호출함
-예외 클래스의 인스턴스를 생성할 때 생성자의 파라미터로 넘겨준 문자열은 내부적으로 저장됨. 이 문장은 예외의 설명에 해당하며 getMassage 메서드를 사용하면 그 문자열을 확인함
6.예외 던지기(throws)
-예외 던지기란 예외가 발생했을 경우 현재 메서드가 예외를 처리하지 않고 자신을 호출한 쪽으로 예외 처리에 대한 책임을 넘기는 것임
-예외 던지기를 할때는 메서드의 선언부에 throws 키워드를 사용해서 예외 던지기를 함
void method( ) throws Exception{ //생략 } |
-만약 다른 예외에 대해서도 예외 던지기를 하려면 쉼표를 쓰고 추가해주면 됨
void method( ) throws Exception{ //생략 } |
-예외 던지기는 호출한 쪽으로 책임을 넘기기 때문에 호출한 쪽에 대해 문법적 강제성이 발생함. 예외를 넘겨받은 쪽은 반드시 직접 예외를 처리하거나 자신도 예외를 던져야 함
cf) 직접: try{ } catch( ) { }
package ch09;
public class exam65 { public static void methodA() throws Exception{ methodB(); } public static void methodB() throws Exception{ methodC(); } public static void methodC() throws Exception{ Exception e = new Exception(); throw e; } public static void main(String[] args) { try { methodA(); } catch (Exception e) { System.out.println("메인에서 처리"); } } } |
실행 결과
메인에서 처리
|
-코드를 보면 main에서 methodA를 호춯하고 methodA가 methodB를 호출하고 methodB가 methodC를 호출함
-마찬가지로 methodB도 예외던지기를 선언하고 있으므로 처리에 대한 책임은 methodA로 넘어가고 마지막으로 main까지 넘어감
-예외는 발생한 곳에서 처리하거나 호출한 곳으로 넘길 수 있기 때문에 개발자는 예외가 발생한 곳에서 바로 처리할지, 넘겨서 처리를 할지 선택해야함. 상황에 따라 선택하는 방식이 다른 것임
'벡엔드 웹프로그래밍 > java' 카테고리의 다른 글
JAVA 프로그래밍 53일차 (25/1/24) (2) | 2025.01.24 |
---|---|
JAVA 프로그래밍 52일차 (25/1/23) (0) | 2025.01.23 |
JAVA 프로그래밍 50일차 (25/1/21) (0) | 2025.01.21 |
JAVA 프로그래밍 49일차 (25/1/20) (2) | 2025.01.20 |
JAVA 프로그래밍 48일차 (25/1/17) (0) | 2025.01.17 |